1 // SPDX-License-Identifier: (GPL-2.0+ OR MIT) 2 /* 3 * Copyright (c) 2018 Microsemi Corporation 4 */ 5 6 #include <common.h> 7 #include <config.h> 8 #include <dm.h> 9 #include <dm/of_access.h> 10 #include <dm/of_addr.h> 11 #include <fdt_support.h> 12 #include <linux/io.h> 13 #include <linux/ioport.h> 14 #include <miiphy.h> 15 #include <net.h> 16 #include <wait_bit.h> 17 18 #include "mscc_miim.h" 19 #include "mscc_xfer.h" 20 #include "mscc_mac_table.h" 21 22 #define PHY_CFG 0x0 23 #define PHY_CFG_ENA 0xF 24 #define PHY_CFG_COMMON_RST BIT(4) 25 #define PHY_CFG_RST (0xF << 5) 26 #define PHY_STAT 0x4 27 #define PHY_STAT_SUPERVISOR_COMPLETE BIT(0) 28 29 #define ANA_PORT_VLAN_CFG(x) (0x7000 + 0x100 * (x)) 30 #define ANA_PORT_VLAN_CFG_AWARE_ENA BIT(20) 31 #define ANA_PORT_VLAN_CFG_POP_CNT(x) ((x) << 18) 32 #define ANA_PORT_PORT_CFG(x) (0x7070 + 0x100 * (x)) 33 #define ANA_PORT_PORT_CFG_RECV_ENA BIT(6) 34 #define ANA_PGID(x) (0x8c00 + 4 * (x)) 35 36 #define SYS_FRM_AGING 0x574 37 #define SYS_FRM_AGING_ENA BIT(20) 38 39 #define SYS_SYSTEM_RST_CFG 0x508 40 #define SYS_SYSTEM_RST_MEM_INIT BIT(0) 41 #define SYS_SYSTEM_RST_MEM_ENA BIT(1) 42 #define SYS_SYSTEM_RST_CORE_ENA BIT(2) 43 #define SYS_PORT_MODE(x) (0x514 + 0x4 * (x)) 44 #define SYS_PORT_MODE_INCL_INJ_HDR(x) ((x) << 3) 45 #define SYS_PORT_MODE_INCL_INJ_HDR_M GENMASK(4, 3) 46 #define SYS_PORT_MODE_INCL_XTR_HDR(x) ((x) << 1) 47 #define SYS_PORT_MODE_INCL_XTR_HDR_M GENMASK(2, 1) 48 #define SYS_PAUSE_CFG(x) (0x608 + 0x4 * (x)) 49 #define SYS_PAUSE_CFG_PAUSE_ENA BIT(0) 50 51 #define QSYS_SWITCH_PORT_MODE(x) (0x11234 + 0x4 * (x)) 52 #define QSYS_SWITCH_PORT_MODE_PORT_ENA BIT(14) 53 #define QSYS_QMAP 0x112d8 54 #define QSYS_EGR_NO_SHARING 0x1129c 55 56 /* Port registers */ 57 #define DEV_CLOCK_CFG 0x0 58 #define DEV_CLOCK_CFG_LINK_SPEED_1000 1 59 #define DEV_MAC_ENA_CFG 0x1c 60 #define DEV_MAC_ENA_CFG_RX_ENA BIT(4) 61 #define DEV_MAC_ENA_CFG_TX_ENA BIT(0) 62 63 #define DEV_MAC_IFG_CFG 0x30 64 #define DEV_MAC_IFG_CFG_TX_IFG(x) ((x) << 8) 65 #define DEV_MAC_IFG_CFG_RX_IFG2(x) ((x) << 4) 66 #define DEV_MAC_IFG_CFG_RX_IFG1(x) (x) 67 68 #define PCS1G_CFG 0x48 69 #define PCS1G_MODE_CFG_SGMII_MODE_ENA BIT(0) 70 #define PCS1G_MODE_CFG 0x4c 71 #define PCS1G_MODE_CFG_UNIDIR_MODE_ENA BIT(4) 72 #define PCS1G_MODE_CFG_SGMII_MODE_ENA BIT(0) 73 #define PCS1G_SD_CFG 0x50 74 #define PCS1G_ANEG_CFG 0x54 75 #define PCS1G_ANEG_CFG_ADV_ABILITY(x) ((x) << 16) 76 77 #define QS_XTR_GRP_CFG(x) (4 * (x)) 78 #define QS_XTR_GRP_CFG_MODE(x) ((x) << 2) 79 #define QS_XTR_GRP_CFG_STATUS_WORD_POS BIT(1) 80 #define QS_XTR_GRP_CFG_BYTE_SWAP BIT(0) 81 #define QS_INJ_GRP_CFG(x) (0x24 + (x) * 4) 82 #define QS_INJ_GRP_CFG_MODE(x) ((x) << 2) 83 #define QS_INJ_GRP_CFG_BYTE_SWAP BIT(0) 84 85 #define IFH_INJ_BYPASS BIT(31) 86 #define IFH_TAG_TYPE_C 0 87 #define MAC_VID 1 88 #define CPU_PORT 11 89 #define INTERNAL_PORT_MSK 0xF 90 #define IFH_LEN 4 91 #define ETH_ALEN 6 92 #define PGID_BROADCAST 13 93 #define PGID_UNICAST 14 94 #define PGID_SRC 80 95 96 enum ocelot_target { 97 ANA, 98 QS, 99 QSYS, 100 REW, 101 SYS, 102 HSIO, 103 PORT0, 104 PORT1, 105 PORT2, 106 PORT3, 107 TARGET_MAX, 108 }; 109 110 #define MAX_PORT (PORT3 - PORT0) 111 112 enum ocelot_mdio_target { 113 MIIM, 114 PHY, 115 TARGET_MDIO_MAX, 116 }; 117 118 enum ocelot_phy_id { 119 INTERNAL, 120 EXTERNAL, 121 NUM_PHY, 122 }; 123 124 struct ocelot_private { 125 void __iomem *regs[TARGET_MAX]; 126 struct mii_dev *bus[NUM_PHY]; 127 }; 128 129 static const unsigned long ocelot_regs_qs[] = { 130 [MSCC_QS_XTR_RD] = 0x8, 131 [MSCC_QS_XTR_FLUSH] = 0x18, 132 [MSCC_QS_XTR_DATA_PRESENT] = 0x1c, 133 [MSCC_QS_INJ_WR] = 0x2c, 134 [MSCC_QS_INJ_CTRL] = 0x34, 135 }; 136 137 static const unsigned long ocelot_regs_ana_table[] = { 138 [MSCC_ANA_TABLES_MACHDATA] = 0x8b34, 139 [MSCC_ANA_TABLES_MACLDATA] = 0x8b38, 140 [MSCC_ANA_TABLES_MACACCESS] = 0x8b3c, 141 }; 142 143 static struct mscc_miim_dev miim[NUM_PHY]; 144 145 static int mscc_miim_reset(struct mii_dev *bus) 146 { 147 struct mscc_miim_dev *miim = (struct mscc_miim_dev *)bus->priv; 148 149 if (miim->phy_regs) { 150 writel(0, miim->phy_regs + PHY_CFG); 151 writel(PHY_CFG_RST | PHY_CFG_COMMON_RST 152 | PHY_CFG_ENA, miim->phy_regs + PHY_CFG); 153 mdelay(500); 154 } 155 156 return 0; 157 } 158 159 /* For now only setup the internal mdio bus */ 160 static struct mii_dev *ocelot_mdiobus_init(struct udevice *dev) 161 { 162 unsigned long phy_size[TARGET_MAX]; 163 phys_addr_t phy_base[TARGET_MAX]; 164 struct ofnode_phandle_args phandle; 165 ofnode eth_node, node, mdio_node; 166 struct resource res; 167 struct mii_dev *bus; 168 fdt32_t faddr; 169 int i; 170 171 bus = mdio_alloc(); 172 173 if (!bus) 174 return NULL; 175 176 /* gathered only the first mdio bus */ 177 eth_node = dev_read_first_subnode(dev); 178 node = ofnode_first_subnode(eth_node); 179 ofnode_parse_phandle_with_args(node, "phy-handle", NULL, 0, 0, 180 &phandle); 181 mdio_node = ofnode_get_parent(phandle.node); 182 183 for (i = 0; i < TARGET_MDIO_MAX; i++) { 184 if (ofnode_read_resource(mdio_node, i, &res)) { 185 pr_err("%s: get OF resource failed\n", __func__); 186 return NULL; 187 } 188 faddr = cpu_to_fdt32(res.start); 189 phy_base[i] = ofnode_translate_address(mdio_node, &faddr); 190 phy_size[i] = res.end - res.start; 191 } 192 193 strcpy(bus->name, "miim-internal"); 194 miim[INTERNAL].phy_regs = ioremap(phy_base[PHY], phy_size[PHY]); 195 miim[INTERNAL].regs = ioremap(phy_base[MIIM], phy_size[MIIM]); 196 bus->priv = &miim[INTERNAL]; 197 bus->reset = mscc_miim_reset; 198 bus->read = mscc_miim_read; 199 bus->write = mscc_miim_write; 200 201 if (mdio_register(bus)) 202 return NULL; 203 else 204 return bus; 205 } 206 207 __weak void mscc_switch_reset(void) 208 { 209 } 210 211 static void ocelot_stop(struct udevice *dev) 212 { 213 struct ocelot_private *priv = dev_get_priv(dev); 214 int i; 215 216 mscc_switch_reset(); 217 for (i = 0; i < NUM_PHY; i++) 218 if (priv->bus[i]) 219 mscc_miim_reset(priv->bus[i]); 220 } 221 222 static void ocelot_cpu_capture_setup(struct ocelot_private *priv) 223 { 224 int i; 225 226 /* map the 8 CPU extraction queues to CPU port 11 */ 227 writel(0, priv->regs[QSYS] + QSYS_QMAP); 228 229 for (i = 0; i <= 1; i++) { 230 /* 231 * Do byte-swap and expect status after last data word 232 * Extraction: Mode: manual extraction) | Byte_swap 233 */ 234 writel(QS_XTR_GRP_CFG_MODE(1) | QS_XTR_GRP_CFG_BYTE_SWAP, 235 priv->regs[QS] + QS_XTR_GRP_CFG(i)); 236 /* 237 * Injection: Mode: manual extraction | Byte_swap 238 */ 239 writel(QS_INJ_GRP_CFG_MODE(1) | QS_INJ_GRP_CFG_BYTE_SWAP, 240 priv->regs[QS] + QS_INJ_GRP_CFG(i)); 241 } 242 243 for (i = 0; i <= 1; i++) 244 /* Enable IFH insertion/parsing on CPU ports */ 245 writel(SYS_PORT_MODE_INCL_INJ_HDR(1) | 246 SYS_PORT_MODE_INCL_XTR_HDR(1), 247 priv->regs[SYS] + SYS_PORT_MODE(CPU_PORT + i)); 248 /* 249 * Setup the CPU port as VLAN aware to support switching frames 250 * based on tags 251 */ 252 writel(ANA_PORT_VLAN_CFG_AWARE_ENA | ANA_PORT_VLAN_CFG_POP_CNT(1) | 253 MAC_VID, priv->regs[ANA] + ANA_PORT_VLAN_CFG(CPU_PORT)); 254 255 /* Disable learning (only RECV_ENA must be set) */ 256 writel(ANA_PORT_PORT_CFG_RECV_ENA, 257 priv->regs[ANA] + ANA_PORT_PORT_CFG(CPU_PORT)); 258 259 /* Enable switching to/from cpu port */ 260 setbits_le32(priv->regs[QSYS] + QSYS_SWITCH_PORT_MODE(CPU_PORT), 261 QSYS_SWITCH_PORT_MODE_PORT_ENA); 262 263 /* No pause on CPU port - not needed (off by default) */ 264 clrbits_le32(priv->regs[SYS] + SYS_PAUSE_CFG(CPU_PORT), 265 SYS_PAUSE_CFG_PAUSE_ENA); 266 267 setbits_le32(priv->regs[QSYS] + QSYS_EGR_NO_SHARING, BIT(CPU_PORT)); 268 } 269 270 static void ocelot_port_init(struct ocelot_private *priv, int port) 271 { 272 void __iomem *regs = priv->regs[port]; 273 274 /* Enable PCS */ 275 writel(PCS1G_MODE_CFG_SGMII_MODE_ENA, regs + PCS1G_CFG); 276 277 /* Disable Signal Detect */ 278 writel(0, regs + PCS1G_SD_CFG); 279 280 /* Enable MAC RX and TX */ 281 writel(DEV_MAC_ENA_CFG_RX_ENA | DEV_MAC_ENA_CFG_TX_ENA, 282 regs + DEV_MAC_ENA_CFG); 283 284 /* Clear sgmii_mode_ena */ 285 writel(0, regs + PCS1G_MODE_CFG); 286 287 /* 288 * Clear sw_resolve_ena(bit 0) and set adv_ability to 289 * something meaningful just in case 290 */ 291 writel(PCS1G_ANEG_CFG_ADV_ABILITY(0x20), regs + PCS1G_ANEG_CFG); 292 293 /* Set MAC IFG Gaps */ 294 writel(DEV_MAC_IFG_CFG_TX_IFG(5) | DEV_MAC_IFG_CFG_RX_IFG1(5) | 295 DEV_MAC_IFG_CFG_RX_IFG2(1), regs + DEV_MAC_IFG_CFG); 296 297 /* Set link speed and release all resets */ 298 writel(DEV_CLOCK_CFG_LINK_SPEED_1000, regs + DEV_CLOCK_CFG); 299 300 /* Make VLAN aware for CPU traffic */ 301 writel(ANA_PORT_VLAN_CFG_AWARE_ENA | ANA_PORT_VLAN_CFG_POP_CNT(1) | 302 MAC_VID, priv->regs[ANA] + ANA_PORT_VLAN_CFG(port - PORT0)); 303 304 /* Enable the port in the core */ 305 setbits_le32(priv->regs[QSYS] + QSYS_SWITCH_PORT_MODE(port - PORT0), 306 QSYS_SWITCH_PORT_MODE_PORT_ENA); 307 } 308 309 static int ocelot_switch_init(struct ocelot_private *priv) 310 { 311 /* Reset switch & memories */ 312 writel(SYS_SYSTEM_RST_MEM_ENA | SYS_SYSTEM_RST_MEM_INIT, 313 priv->regs[SYS] + SYS_SYSTEM_RST_CFG); 314 315 /* Wait to complete */ 316 if (wait_for_bit_le32(priv->regs[SYS] + SYS_SYSTEM_RST_CFG, 317 SYS_SYSTEM_RST_MEM_INIT, false, 2000, false)) { 318 pr_err("Timeout in memory reset\n"); 319 return -EIO; 320 } 321 322 /* Enable switch core */ 323 setbits_le32(priv->regs[SYS] + SYS_SYSTEM_RST_CFG, 324 SYS_SYSTEM_RST_CORE_ENA); 325 326 return 0; 327 } 328 329 static int ocelot_initialize(struct ocelot_private *priv) 330 { 331 int ret, i; 332 333 /* Initialize switch memories, enable core */ 334 ret = ocelot_switch_init(priv); 335 if (ret) 336 return ret; 337 /* 338 * Disable port-to-port by switching 339 * Put fron ports in "port isolation modes" - i.e. they cant send 340 * to other ports - via the PGID sorce masks. 341 */ 342 for (i = 0; i <= MAX_PORT; i++) 343 writel(0, priv->regs[ANA] + ANA_PGID(PGID_SRC + i)); 344 345 /* Flush queues */ 346 mscc_flush(priv->regs[QS], ocelot_regs_qs); 347 348 /* Setup frame ageing - "2 sec" - The unit is 6.5us on Ocelot */ 349 writel(SYS_FRM_AGING_ENA | (20000000 / 65), 350 priv->regs[SYS] + SYS_FRM_AGING); 351 352 for (i = PORT0; i <= PORT3; i++) 353 ocelot_port_init(priv, i); 354 355 ocelot_cpu_capture_setup(priv); 356 357 debug("Ports enabled\n"); 358 359 return 0; 360 } 361 362 static int ocelot_write_hwaddr(struct udevice *dev) 363 { 364 struct ocelot_private *priv = dev_get_priv(dev); 365 struct eth_pdata *pdata = dev_get_platdata(dev); 366 367 mscc_mac_table_add(priv->regs[ANA], ocelot_regs_ana_table, 368 pdata->enetaddr, PGID_UNICAST); 369 370 writel(BIT(CPU_PORT), priv->regs[ANA] + ANA_PGID(PGID_UNICAST)); 371 372 return 0; 373 } 374 375 static int ocelot_start(struct udevice *dev) 376 { 377 struct ocelot_private *priv = dev_get_priv(dev); 378 struct eth_pdata *pdata = dev_get_platdata(dev); 379 const unsigned char mac[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 380 0xff }; 381 int ret; 382 383 ret = ocelot_initialize(priv); 384 if (ret) 385 return ret; 386 387 /* Set MAC address tables entries for CPU redirection */ 388 mscc_mac_table_add(priv->regs[ANA], ocelot_regs_ana_table, mac, 389 PGID_BROADCAST); 390 391 writel(BIT(CPU_PORT) | INTERNAL_PORT_MSK, 392 priv->regs[ANA] + ANA_PGID(PGID_BROADCAST)); 393 394 /* It should be setup latter in ocelot_write_hwaddr */ 395 mscc_mac_table_add(priv->regs[ANA], ocelot_regs_ana_table, 396 pdata->enetaddr, PGID_UNICAST); 397 398 writel(BIT(CPU_PORT), priv->regs[ANA] + ANA_PGID(PGID_UNICAST)); 399 400 return 0; 401 } 402 403 static int ocelot_send(struct udevice *dev, void *packet, int length) 404 { 405 struct ocelot_private *priv = dev_get_priv(dev); 406 u32 ifh[IFH_LEN]; 407 int port = BIT(0); /* use port 0 */ 408 u32 *buf = packet; 409 410 /* 411 * Generate the IFH for frame injection 412 * 413 * The IFH is a 128bit-value 414 * bit 127: bypass the analyzer processing 415 * bit 56-67: destination mask 416 * bit 28-29: pop_cnt: 3 disables all rewriting of the frame 417 * bit 20-27: cpu extraction queue mask 418 * bit 16: tag type 0: C-tag, 1: S-tag 419 * bit 0-11: VID 420 */ 421 ifh[0] = IFH_INJ_BYPASS; 422 ifh[1] = (0xf00 & port) >> 8; 423 ifh[2] = (0xff & port) << 24; 424 ifh[3] = (IFH_TAG_TYPE_C << 16); 425 426 return mscc_send(priv->regs[QS], ocelot_regs_qs, 427 ifh, IFH_LEN, buf, length); 428 } 429 430 static int ocelot_recv(struct udevice *dev, int flags, uchar **packetp) 431 { 432 struct ocelot_private *priv = dev_get_priv(dev); 433 u32 *rxbuf = (u32 *)net_rx_packets[0]; 434 int byte_cnt; 435 436 byte_cnt = mscc_recv(priv->regs[QS], ocelot_regs_qs, rxbuf, IFH_LEN, 437 false); 438 439 *packetp = net_rx_packets[0]; 440 441 return byte_cnt; 442 } 443 444 static int ocelot_probe(struct udevice *dev) 445 { 446 struct ocelot_private *priv = dev_get_priv(dev); 447 int ret, i; 448 449 struct { 450 enum ocelot_target id; 451 char *name; 452 } reg[] = { 453 { SYS, "sys" }, 454 { REW, "rew" }, 455 { QSYS, "qsys" }, 456 { ANA, "ana" }, 457 { QS, "qs" }, 458 { HSIO, "hsio" }, 459 { PORT0, "port0" }, 460 { PORT1, "port1" }, 461 { PORT2, "port2" }, 462 { PORT3, "port3" }, 463 }; 464 465 for (i = 0; i < ARRAY_SIZE(reg); i++) { 466 priv->regs[reg[i].id] = dev_remap_addr_name(dev, reg[i].name); 467 if (!priv->regs[reg[i].id]) { 468 pr_err 469 ("Error %d: can't get regs base addresses for %s\n", 470 ret, reg[i].name); 471 return -ENOMEM; 472 } 473 } 474 475 priv->bus[INTERNAL] = ocelot_mdiobus_init(dev); 476 477 for (i = 0; i < 4; i++) { 478 phy_connect(priv->bus[INTERNAL], i, dev, 479 PHY_INTERFACE_MODE_NONE); 480 } 481 482 return 0; 483 } 484 485 static int ocelot_remove(struct udevice *dev) 486 { 487 struct ocelot_private *priv = dev_get_priv(dev); 488 int i; 489 490 for (i = 0; i < NUM_PHY; i++) { 491 mdio_unregister(priv->bus[i]); 492 mdio_free(priv->bus[i]); 493 } 494 495 return 0; 496 } 497 498 static const struct eth_ops ocelot_ops = { 499 .start = ocelot_start, 500 .stop = ocelot_stop, 501 .send = ocelot_send, 502 .recv = ocelot_recv, 503 .write_hwaddr = ocelot_write_hwaddr, 504 }; 505 506 static const struct udevice_id mscc_ocelot_ids[] = { 507 {.compatible = "mscc,vsc7514-switch"}, 508 { /* Sentinel */ } 509 }; 510 511 U_BOOT_DRIVER(ocelot) = { 512 .name = "ocelot-switch", 513 .id = UCLASS_ETH, 514 .of_match = mscc_ocelot_ids, 515 .probe = ocelot_probe, 516 .remove = ocelot_remove, 517 .ops = &ocelot_ops, 518 .priv_auto_alloc_size = sizeof(struct ocelot_private), 519 .platdata_auto_alloc_size = sizeof(struct eth_pdata), 520 }; 521