1 // SPDX-License-Identifier: GPL-2.0 2 /* ICSSG Ethernet driver 3 * 4 * Copyright (C) 2022 Texas Instruments Incorporated - https://www.ti.com 5 */ 6 7 #include <linux/iopoll.h> 8 #include <linux/regmap.h> 9 #include <uapi/linux/if_ether.h> 10 #include "icssg_config.h" 11 #include "icssg_prueth.h" 12 #include "icssg_switch_map.h" 13 #include "icssg_mii_rt.h" 14 15 /* TX IPG Values to be set for 100M link speed. These values are 16 * in ocp_clk cycles. So need change if ocp_clk is changed for a specific 17 * h/w design. 18 */ 19 20 /* IPG is in core_clk cycles */ 21 #define MII_RT_TX_IPG_100M 0x17 22 #define MII_RT_TX_IPG_1G 0xb 23 #define MII_RT_TX_IPG_100M_SR1 0x166 24 #define MII_RT_TX_IPG_1G_SR1 0x1a 25 26 #define ICSSG_QUEUES_MAX 64 27 #define ICSSG_QUEUE_OFFSET 0xd00 28 #define ICSSG_QUEUE_PEEK_OFFSET 0xe00 29 #define ICSSG_QUEUE_CNT_OFFSET 0xe40 30 #define ICSSG_QUEUE_RESET_OFFSET 0xf40 31 32 #define ICSSG_NUM_TX_QUEUES 8 33 34 #define RECYCLE_Q_SLICE0 16 35 #define RECYCLE_Q_SLICE1 17 36 37 #define ICSSG_NUM_OTHER_QUEUES 5 /* port, host and special queues */ 38 39 #define PORT_HI_Q_SLICE0 32 40 #define PORT_LO_Q_SLICE0 33 41 #define HOST_HI_Q_SLICE0 34 42 #define HOST_LO_Q_SLICE0 35 43 #define HOST_SPL_Q_SLICE0 40 /* Special Queue */ 44 45 #define PORT_HI_Q_SLICE1 36 46 #define PORT_LO_Q_SLICE1 37 47 #define HOST_HI_Q_SLICE1 38 48 #define HOST_LO_Q_SLICE1 39 49 #define HOST_SPL_Q_SLICE1 41 /* Special Queue */ 50 51 #define MII_RXCFG_DEFAULT (PRUSS_MII_RT_RXCFG_RX_ENABLE | \ 52 PRUSS_MII_RT_RXCFG_RX_DATA_RDY_MODE_DIS | \ 53 PRUSS_MII_RT_RXCFG_RX_L2_EN | \ 54 PRUSS_MII_RT_RXCFG_RX_L2_EOF_SCLR_DIS) 55 56 #define MII_TXCFG_DEFAULT (PRUSS_MII_RT_TXCFG_TX_ENABLE | \ 57 PRUSS_MII_RT_TXCFG_TX_AUTO_PREAMBLE | \ 58 PRUSS_MII_RT_TXCFG_TX_32_MODE_EN | \ 59 PRUSS_MII_RT_TXCFG_TX_IPG_WIRE_CLK_EN) 60 61 #define ICSSG_CFG_DEFAULT (ICSSG_CFG_TX_L1_EN | \ 62 ICSSG_CFG_TX_L2_EN | ICSSG_CFG_RX_L2_G_EN | \ 63 ICSSG_CFG_TX_PRU_EN | \ 64 ICSSG_CFG_SGMII_MODE) 65 66 #define FDB_GEN_CFG1 0x60 67 #define SMEM_VLAN_OFFSET 8 68 #define SMEM_VLAN_OFFSET_MASK GENMASK(25, 8) 69 70 #define FDB_GEN_CFG2 0x64 71 #define FDB_VLAN_EN BIT(6) 72 #define FDB_HOST_EN BIT(2) 73 #define FDB_PRU1_EN BIT(1) 74 #define FDB_PRU0_EN BIT(0) 75 #define FDB_EN_ALL (FDB_PRU0_EN | FDB_PRU1_EN | \ 76 FDB_HOST_EN | FDB_VLAN_EN) 77 78 /** 79 * struct map - ICSSG Queue Map 80 * @queue: Queue number 81 * @pd_addr_start: Packet descriptor queue reserved memory 82 * @flags: Flags 83 * @special: Indicates whether this queue is a special queue or not 84 */ 85 struct map { 86 int queue; 87 u32 pd_addr_start; 88 u32 flags; 89 bool special; 90 }; 91 92 /* Hardware queue map for ICSSG */ 93 static const struct map hwq_map[2][ICSSG_NUM_OTHER_QUEUES] = { 94 { 95 { PORT_HI_Q_SLICE0, PORT_DESC0_HI, 0x200000, 0 }, 96 { PORT_LO_Q_SLICE0, PORT_DESC0_LO, 0, 0 }, 97 { HOST_HI_Q_SLICE0, HOST_DESC0_HI, 0x200000, 0 }, 98 { HOST_LO_Q_SLICE0, HOST_DESC0_LO, 0, 0 }, 99 { HOST_SPL_Q_SLICE0, HOST_SPPD0, 0x400000, 1 }, 100 }, 101 { 102 { PORT_HI_Q_SLICE1, PORT_DESC1_HI, 0xa00000, 0 }, 103 { PORT_LO_Q_SLICE1, PORT_DESC1_LO, 0x800000, 0 }, 104 { HOST_HI_Q_SLICE1, HOST_DESC1_HI, 0xa00000, 0 }, 105 { HOST_LO_Q_SLICE1, HOST_DESC1_LO, 0x800000, 0 }, 106 { HOST_SPL_Q_SLICE1, HOST_SPPD1, 0xc00000, 1 }, 107 }, 108 }; 109 110 static void icssg_config_mii_init_switch(struct prueth_emac *emac) 111 { 112 struct prueth *prueth = emac->prueth; 113 int mii = prueth_emac_slice(emac); 114 u32 txcfg_reg, pcnt_reg, txcfg; 115 struct regmap *mii_rt; 116 117 mii_rt = prueth->mii_rt; 118 119 txcfg_reg = (mii == ICSS_MII0) ? PRUSS_MII_RT_TXCFG0 : 120 PRUSS_MII_RT_TXCFG1; 121 pcnt_reg = (mii == ICSS_MII0) ? PRUSS_MII_RT_RX_PCNT0 : 122 PRUSS_MII_RT_RX_PCNT1; 123 124 txcfg = PRUSS_MII_RT_TXCFG_TX_ENABLE | 125 PRUSS_MII_RT_TXCFG_TX_AUTO_PREAMBLE | 126 PRUSS_MII_RT_TXCFG_TX_IPG_WIRE_CLK_EN; 127 128 if (emac->phy_if == PHY_INTERFACE_MODE_MII && mii == ICSS_MII1) 129 txcfg |= PRUSS_MII_RT_TXCFG_TX_MUX_SEL; 130 else if (emac->phy_if != PHY_INTERFACE_MODE_MII && mii == ICSS_MII0) 131 txcfg |= PRUSS_MII_RT_TXCFG_TX_MUX_SEL; 132 133 regmap_write(mii_rt, txcfg_reg, txcfg); 134 regmap_write(mii_rt, pcnt_reg, 0x1); 135 } 136 137 static void icssg_config_mii_init(struct prueth_emac *emac) 138 { 139 struct prueth *prueth = emac->prueth; 140 int slice = prueth_emac_slice(emac); 141 u32 txcfg, txcfg_reg, pcnt_reg; 142 struct regmap *mii_rt; 143 144 mii_rt = prueth->mii_rt; 145 146 txcfg_reg = (slice == ICSS_MII0) ? PRUSS_MII_RT_TXCFG0 : 147 PRUSS_MII_RT_TXCFG1; 148 pcnt_reg = (slice == ICSS_MII0) ? PRUSS_MII_RT_RX_PCNT0 : 149 PRUSS_MII_RT_RX_PCNT1; 150 151 txcfg = MII_TXCFG_DEFAULT; 152 153 /* In MII mode TX lines swapped inside ICSSG, so TX_MUX_SEL cfg need 154 * to be swapped also comparing to RGMII mode. 155 */ 156 if (emac->phy_if == PHY_INTERFACE_MODE_MII && slice == ICSS_MII0) 157 txcfg |= PRUSS_MII_RT_TXCFG_TX_MUX_SEL; 158 else if (emac->phy_if != PHY_INTERFACE_MODE_MII && slice == ICSS_MII1) 159 txcfg |= PRUSS_MII_RT_TXCFG_TX_MUX_SEL; 160 161 regmap_write(mii_rt, txcfg_reg, txcfg); 162 regmap_write(mii_rt, pcnt_reg, 0x1); 163 } 164 165 static void icssg_miig_queues_init(struct prueth *prueth, int slice) 166 { 167 struct regmap *miig_rt = prueth->miig_rt; 168 void __iomem *smem = prueth->shram.va; 169 u8 pd[ICSSG_SPECIAL_PD_SIZE]; 170 int queue = 0, i, j; 171 u32 *pdword; 172 173 /* reset hwqueues */ 174 if (slice) 175 queue = ICSSG_NUM_TX_QUEUES; 176 177 for (i = 0; i < ICSSG_NUM_TX_QUEUES; i++) { 178 regmap_write(miig_rt, ICSSG_QUEUE_RESET_OFFSET, queue); 179 queue++; 180 } 181 182 queue = slice ? RECYCLE_Q_SLICE1 : RECYCLE_Q_SLICE0; 183 regmap_write(miig_rt, ICSSG_QUEUE_RESET_OFFSET, queue); 184 185 for (i = 0; i < ICSSG_NUM_OTHER_QUEUES; i++) { 186 regmap_write(miig_rt, ICSSG_QUEUE_RESET_OFFSET, 187 hwq_map[slice][i].queue); 188 } 189 190 /* initialize packet descriptors in SMEM */ 191 /* push pakcet descriptors to hwqueues */ 192 193 pdword = (u32 *)pd; 194 for (j = 0; j < ICSSG_NUM_OTHER_QUEUES; j++) { 195 const struct map *mp; 196 int pd_size, num_pds; 197 u32 pdaddr; 198 199 mp = &hwq_map[slice][j]; 200 if (mp->special) { 201 pd_size = ICSSG_SPECIAL_PD_SIZE; 202 num_pds = ICSSG_NUM_SPECIAL_PDS; 203 } else { 204 pd_size = ICSSG_NORMAL_PD_SIZE; 205 num_pds = ICSSG_NUM_NORMAL_PDS; 206 } 207 208 for (i = 0; i < num_pds; i++) { 209 memset(pd, 0, pd_size); 210 211 pdword[0] &= ICSSG_FLAG_MASK; 212 pdword[0] |= mp->flags; 213 pdaddr = mp->pd_addr_start + i * pd_size; 214 215 memcpy_toio(smem + pdaddr, pd, pd_size); 216 queue = mp->queue; 217 regmap_write(miig_rt, ICSSG_QUEUE_OFFSET + 4 * queue, 218 pdaddr); 219 } 220 } 221 } 222 223 void icssg_config_ipg(struct prueth_emac *emac) 224 { 225 struct prueth *prueth = emac->prueth; 226 int slice = prueth_emac_slice(emac); 227 u32 ipg; 228 229 switch (emac->speed) { 230 case SPEED_1000: 231 ipg = emac->is_sr1 ? MII_RT_TX_IPG_1G_SR1 : MII_RT_TX_IPG_1G; 232 break; 233 case SPEED_100: 234 ipg = emac->is_sr1 ? MII_RT_TX_IPG_100M_SR1 : MII_RT_TX_IPG_100M; 235 break; 236 case SPEED_10: 237 /* Firmware hardcodes IPG for SR1.0 */ 238 if (emac->is_sr1) 239 return; 240 /* IPG for 10M is same as 100M */ 241 ipg = MII_RT_TX_IPG_100M; 242 break; 243 default: 244 /* Other links speeds not supported */ 245 netdev_err(emac->ndev, "Unsupported link speed\n"); 246 return; 247 } 248 249 icssg_mii_update_ipg(prueth->mii_rt, slice, ipg); 250 } 251 252 static void emac_r30_cmd_init(struct prueth_emac *emac) 253 { 254 struct icssg_r30_cmd __iomem *p; 255 int i; 256 257 p = emac->dram.va + MGR_R30_CMD_OFFSET; 258 259 for (i = 0; i < 4; i++) 260 writel(EMAC_NONE, &p->cmd[i]); 261 } 262 263 static int emac_r30_is_done(struct prueth_emac *emac) 264 { 265 const struct icssg_r30_cmd __iomem *p; 266 u32 cmd; 267 int i; 268 269 p = emac->dram.va + MGR_R30_CMD_OFFSET; 270 271 for (i = 0; i < 4; i++) { 272 cmd = readl(&p->cmd[i]); 273 if (cmd != EMAC_NONE) 274 return 0; 275 } 276 277 return 1; 278 } 279 280 static int prueth_switch_buffer_setup(struct prueth_emac *emac) 281 { 282 struct icssg_buffer_pool_cfg __iomem *bpool_cfg; 283 struct icssg_rxq_ctx __iomem *rxq_ctx; 284 struct prueth *prueth = emac->prueth; 285 int slice = prueth_emac_slice(emac); 286 u32 addr; 287 int i; 288 289 addr = lower_32_bits(prueth->msmcram.pa); 290 if (slice) 291 addr += PRUETH_NUM_BUF_POOLS * PRUETH_EMAC_BUF_POOL_SIZE; 292 293 if (addr % SZ_64K) { 294 dev_warn(prueth->dev, "buffer pool needs to be 64KB aligned\n"); 295 return -EINVAL; 296 } 297 298 bpool_cfg = emac->dram.va + BUFFER_POOL_0_ADDR_OFFSET; 299 /* workaround for f/w bug. bpool 0 needs to be initialized */ 300 for (i = 0; i < PRUETH_NUM_BUF_POOLS; i++) { 301 writel(addr, &bpool_cfg[i].addr); 302 writel(PRUETH_EMAC_BUF_POOL_SIZE, &bpool_cfg[i].len); 303 addr += PRUETH_EMAC_BUF_POOL_SIZE; 304 } 305 306 if (!slice) 307 addr += PRUETH_NUM_BUF_POOLS * PRUETH_EMAC_BUF_POOL_SIZE; 308 else 309 addr += PRUETH_SW_NUM_BUF_POOLS_HOST * PRUETH_SW_BUF_POOL_SIZE_HOST; 310 311 for (i = PRUETH_NUM_BUF_POOLS; 312 i < 2 * PRUETH_SW_NUM_BUF_POOLS_HOST + PRUETH_NUM_BUF_POOLS; 313 i++) { 314 /* The driver only uses first 4 queues per PRU so only initialize them */ 315 if (i % PRUETH_SW_NUM_BUF_POOLS_HOST < PRUETH_SW_NUM_BUF_POOLS_PER_PRU) { 316 writel(addr, &bpool_cfg[i].addr); 317 writel(PRUETH_SW_BUF_POOL_SIZE_HOST, &bpool_cfg[i].len); 318 addr += PRUETH_SW_BUF_POOL_SIZE_HOST; 319 } else { 320 writel(0, &bpool_cfg[i].addr); 321 writel(0, &bpool_cfg[i].len); 322 } 323 } 324 325 if (!slice) 326 addr += PRUETH_SW_NUM_BUF_POOLS_HOST * PRUETH_SW_BUF_POOL_SIZE_HOST; 327 else 328 addr += PRUETH_EMAC_RX_CTX_BUF_SIZE; 329 330 rxq_ctx = emac->dram.va + HOST_RX_Q_PRE_CONTEXT_OFFSET; 331 for (i = 0; i < 3; i++) 332 writel(addr, &rxq_ctx->start[i]); 333 334 addr += PRUETH_EMAC_RX_CTX_BUF_SIZE; 335 writel(addr - SZ_2K, &rxq_ctx->end); 336 337 return 0; 338 } 339 340 static int prueth_emac_buffer_setup(struct prueth_emac *emac) 341 { 342 struct icssg_buffer_pool_cfg __iomem *bpool_cfg; 343 struct icssg_rxq_ctx __iomem *rxq_ctx; 344 struct prueth *prueth = emac->prueth; 345 int slice = prueth_emac_slice(emac); 346 u32 addr; 347 int i; 348 349 /* Layout to have 64KB aligned buffer pool 350 * |BPOOL0|BPOOL1|RX_CTX0|RX_CTX1| 351 */ 352 353 addr = lower_32_bits(prueth->msmcram.pa); 354 if (slice) 355 addr += PRUETH_NUM_BUF_POOLS * PRUETH_EMAC_BUF_POOL_SIZE; 356 357 if (addr % SZ_64K) { 358 dev_warn(prueth->dev, "buffer pool needs to be 64KB aligned\n"); 359 return -EINVAL; 360 } 361 362 bpool_cfg = emac->dram.va + BUFFER_POOL_0_ADDR_OFFSET; 363 /* workaround for f/w bug. bpool 0 needs to be initilalized */ 364 writel(addr, &bpool_cfg[0].addr); 365 writel(0, &bpool_cfg[0].len); 366 367 for (i = PRUETH_EMAC_BUF_POOL_START; 368 i < PRUETH_EMAC_BUF_POOL_START + PRUETH_NUM_BUF_POOLS; 369 i++) { 370 writel(addr, &bpool_cfg[i].addr); 371 writel(PRUETH_EMAC_BUF_POOL_SIZE, &bpool_cfg[i].len); 372 addr += PRUETH_EMAC_BUF_POOL_SIZE; 373 } 374 375 if (!slice) 376 addr += PRUETH_NUM_BUF_POOLS * PRUETH_EMAC_BUF_POOL_SIZE; 377 else 378 addr += PRUETH_EMAC_RX_CTX_BUF_SIZE * 2; 379 380 /* Pre-emptible RX buffer queue */ 381 rxq_ctx = emac->dram.va + HOST_RX_Q_PRE_CONTEXT_OFFSET; 382 for (i = 0; i < 3; i++) 383 writel(addr, &rxq_ctx->start[i]); 384 385 addr += PRUETH_EMAC_RX_CTX_BUF_SIZE; 386 writel(addr, &rxq_ctx->end); 387 388 /* Express RX buffer queue */ 389 rxq_ctx = emac->dram.va + HOST_RX_Q_EXP_CONTEXT_OFFSET; 390 for (i = 0; i < 3; i++) 391 writel(addr, &rxq_ctx->start[i]); 392 393 addr += PRUETH_EMAC_RX_CTX_BUF_SIZE; 394 writel(addr, &rxq_ctx->end); 395 396 return 0; 397 } 398 399 static void icssg_init_emac_mode(struct prueth *prueth) 400 { 401 /* When the device is configured as a bridge and it is being brought 402 * back to the emac mode, the host mac address has to be set as 0. 403 */ 404 u32 addr = prueth->shram.pa + EMAC_ICSSG_SWITCH_DEFAULT_VLAN_TABLE_OFFSET; 405 int i; 406 u8 mac[ETH_ALEN] = { 0 }; 407 408 if (prueth->emacs_initialized) 409 return; 410 411 /* Set VLAN TABLE address base */ 412 regmap_update_bits(prueth->miig_rt, FDB_GEN_CFG1, SMEM_VLAN_OFFSET_MASK, 413 addr << SMEM_VLAN_OFFSET); 414 /* Set enable VLAN aware mode, and FDBs for all PRUs */ 415 regmap_write(prueth->miig_rt, FDB_GEN_CFG2, (FDB_PRU0_EN | FDB_PRU1_EN | FDB_HOST_EN)); 416 prueth->vlan_tbl = (struct prueth_vlan_tbl __force *)(prueth->shram.va + 417 EMAC_ICSSG_SWITCH_DEFAULT_VLAN_TABLE_OFFSET); 418 for (i = 0; i < SZ_4K - 1; i++) { 419 prueth->vlan_tbl[i].fid = i; 420 prueth->vlan_tbl[i].fid_c1 = 0; 421 } 422 /* Clear host MAC address */ 423 icssg_class_set_host_mac_addr(prueth->miig_rt, mac); 424 } 425 426 static void icssg_init_switch_mode(struct prueth *prueth) 427 { 428 u32 addr = prueth->shram.pa + EMAC_ICSSG_SWITCH_DEFAULT_VLAN_TABLE_OFFSET; 429 int i; 430 431 if (prueth->emacs_initialized) 432 return; 433 434 /* Set VLAN TABLE address base */ 435 regmap_update_bits(prueth->miig_rt, FDB_GEN_CFG1, SMEM_VLAN_OFFSET_MASK, 436 addr << SMEM_VLAN_OFFSET); 437 /* Set enable VLAN aware mode, and FDBs for all PRUs */ 438 regmap_write(prueth->miig_rt, FDB_GEN_CFG2, FDB_EN_ALL); 439 prueth->vlan_tbl = (struct prueth_vlan_tbl __force *)(prueth->shram.va + 440 EMAC_ICSSG_SWITCH_DEFAULT_VLAN_TABLE_OFFSET); 441 for (i = 0; i < SZ_4K - 1; i++) { 442 prueth->vlan_tbl[i].fid = i; 443 prueth->vlan_tbl[i].fid_c1 = 0; 444 } 445 446 if (prueth->hw_bridge_dev) 447 icssg_class_set_host_mac_addr(prueth->miig_rt, prueth->hw_bridge_dev->dev_addr); 448 icssg_set_pvid(prueth, prueth->default_vlan, PRUETH_PORT_HOST); 449 } 450 451 int icssg_config(struct prueth *prueth, struct prueth_emac *emac, int slice) 452 { 453 void __iomem *config = emac->dram.va + ICSSG_CONFIG_OFFSET; 454 struct icssg_flow_cfg __iomem *flow_cfg; 455 int ret; 456 457 if (prueth->is_switch_mode) 458 icssg_init_switch_mode(prueth); 459 else 460 icssg_init_emac_mode(prueth); 461 462 memset_io(config, 0, TAS_GATE_MASK_LIST0); 463 icssg_miig_queues_init(prueth, slice); 464 465 emac->speed = SPEED_1000; 466 emac->duplex = DUPLEX_FULL; 467 if (!phy_interface_mode_is_rgmii(emac->phy_if)) { 468 emac->speed = SPEED_100; 469 emac->duplex = DUPLEX_FULL; 470 } 471 regmap_update_bits(prueth->miig_rt, ICSSG_CFG_OFFSET, 472 ICSSG_CFG_DEFAULT, ICSSG_CFG_DEFAULT); 473 icssg_miig_set_interface_mode(prueth->miig_rt, slice, emac->phy_if); 474 if (prueth->is_switch_mode) 475 icssg_config_mii_init_switch(emac); 476 else 477 icssg_config_mii_init(emac); 478 icssg_config_ipg(emac); 479 icssg_update_rgmii_cfg(prueth->miig_rt, emac); 480 481 /* set GPI mode */ 482 pruss_cfg_gpimode(prueth->pruss, prueth->pru_id[slice], 483 PRUSS_GPI_MODE_MII); 484 485 /* enable XFR shift for PRU and RTU */ 486 pruss_cfg_xfr_enable(prueth->pruss, PRU_TYPE_PRU, true); 487 pruss_cfg_xfr_enable(prueth->pruss, PRU_TYPE_RTU, true); 488 489 /* set C28 to 0x100 */ 490 pru_rproc_set_ctable(prueth->pru[slice], PRU_C28, 0x100 << 8); 491 pru_rproc_set_ctable(prueth->rtu[slice], PRU_C28, 0x100 << 8); 492 pru_rproc_set_ctable(prueth->txpru[slice], PRU_C28, 0x100 << 8); 493 494 flow_cfg = config + PSI_L_REGULAR_FLOW_ID_BASE_OFFSET; 495 writew(emac->rx_flow_id_base, &flow_cfg->rx_base_flow); 496 writew(0, &flow_cfg->mgm_base_flow); 497 writeb(0, config + SPL_PKT_DEFAULT_PRIORITY); 498 writeb(0, config + QUEUE_NUM_UNTAGGED); 499 500 if (prueth->is_switch_mode) 501 ret = prueth_switch_buffer_setup(emac); 502 else 503 ret = prueth_emac_buffer_setup(emac); 504 if (ret) 505 return ret; 506 507 emac_r30_cmd_init(emac); 508 509 return 0; 510 } 511 512 /* Bitmask for ICSSG r30 commands */ 513 static const struct icssg_r30_cmd emac_r32_bitmask[] = { 514 {{0xffff0004, 0xffff0100, 0xffff0004, EMAC_NONE}}, /* EMAC_PORT_DISABLE */ 515 {{0xfffb0040, 0xfeff0200, 0xfeff0200, EMAC_NONE}}, /* EMAC_PORT_BLOCK */ 516 {{0xffbb0000, 0xfcff0000, 0xdcfb0000, EMAC_NONE}}, /* EMAC_PORT_FORWARD */ 517 {{0xffbb0000, 0xfcff0000, 0xfcff2000, EMAC_NONE}}, /* EMAC_PORT_FORWARD_WO_LEARNING */ 518 {{0xffff0001, EMAC_NONE, EMAC_NONE, EMAC_NONE}}, /* ACCEPT ALL */ 519 {{0xfffe0002, EMAC_NONE, EMAC_NONE, EMAC_NONE}}, /* ACCEPT TAGGED */ 520 {{0xfffc0000, EMAC_NONE, EMAC_NONE, EMAC_NONE}}, /* ACCEPT UNTAGGED and PRIO */ 521 {{EMAC_NONE, 0xffff0020, EMAC_NONE, EMAC_NONE}}, /* TAS Trigger List change */ 522 {{EMAC_NONE, 0xdfff1000, EMAC_NONE, EMAC_NONE}}, /* TAS set state ENABLE*/ 523 {{EMAC_NONE, 0xefff2000, EMAC_NONE, EMAC_NONE}}, /* TAS set state RESET*/ 524 {{EMAC_NONE, 0xcfff0000, EMAC_NONE, EMAC_NONE}}, /* TAS set state DISABLE*/ 525 {{EMAC_NONE, EMAC_NONE, 0xffff0400, EMAC_NONE}}, /* UC flooding ENABLE*/ 526 {{EMAC_NONE, EMAC_NONE, 0xfbff0000, EMAC_NONE}}, /* UC flooding DISABLE*/ 527 {{EMAC_NONE, EMAC_NONE, 0xffff0800, EMAC_NONE}}, /* MC flooding ENABLE*/ 528 {{EMAC_NONE, EMAC_NONE, 0xf7ff0000, EMAC_NONE}}, /* MC flooding DISABLE*/ 529 {{EMAC_NONE, 0xffff4000, EMAC_NONE, EMAC_NONE}}, /* Preemption on Tx ENABLE*/ 530 {{EMAC_NONE, 0xbfff0000, EMAC_NONE, EMAC_NONE}}, /* Preemption on Tx DISABLE*/ 531 {{0xffff0010, EMAC_NONE, 0xffff0010, EMAC_NONE}}, /* VLAN AWARE*/ 532 {{0xffef0000, EMAC_NONE, 0xffef0000, EMAC_NONE}} /* VLAN UNWARE*/ 533 }; 534 535 int emac_set_port_state(struct prueth_emac *emac, 536 enum icssg_port_state_cmd cmd) 537 { 538 struct icssg_r30_cmd __iomem *p; 539 int ret = -ETIMEDOUT; 540 int done = 0; 541 int i; 542 543 p = emac->dram.va + MGR_R30_CMD_OFFSET; 544 545 if (cmd >= ICSSG_EMAC_PORT_MAX_COMMANDS) { 546 netdev_err(emac->ndev, "invalid port command\n"); 547 return -EINVAL; 548 } 549 550 /* only one command at a time allowed to firmware */ 551 mutex_lock(&emac->cmd_lock); 552 553 for (i = 0; i < 4; i++) 554 writel(emac_r32_bitmask[cmd].cmd[i], &p->cmd[i]); 555 556 /* wait for done */ 557 ret = read_poll_timeout(emac_r30_is_done, done, done == 1, 558 1000, 10000, false, emac); 559 560 if (ret == -ETIMEDOUT) 561 netdev_err(emac->ndev, "timeout waiting for command done\n"); 562 563 mutex_unlock(&emac->cmd_lock); 564 565 return ret; 566 } 567 568 void icssg_config_half_duplex(struct prueth_emac *emac) 569 { 570 u32 val; 571 572 if (!emac->half_duplex) 573 return; 574 575 val = get_random_u32(); 576 writel(val, emac->dram.va + HD_RAND_SEED_OFFSET); 577 } 578 579 void icssg_config_set_speed(struct prueth_emac *emac) 580 { 581 u8 fw_speed; 582 583 switch (emac->speed) { 584 case SPEED_1000: 585 fw_speed = FW_LINK_SPEED_1G; 586 break; 587 case SPEED_100: 588 fw_speed = FW_LINK_SPEED_100M; 589 break; 590 case SPEED_10: 591 fw_speed = FW_LINK_SPEED_10M; 592 break; 593 default: 594 /* Other links speeds not supported */ 595 netdev_err(emac->ndev, "Unsupported link speed\n"); 596 return; 597 } 598 599 if (emac->duplex == DUPLEX_HALF) 600 fw_speed |= FW_LINK_SPEED_HD; 601 602 writeb(fw_speed, emac->dram.va + PORT_LINK_SPEED_OFFSET); 603 } 604 605 int icssg_send_fdb_msg(struct prueth_emac *emac, struct mgmt_cmd *cmd, 606 struct mgmt_cmd_rsp *rsp) 607 { 608 struct prueth *prueth = emac->prueth; 609 int slice = prueth_emac_slice(emac); 610 int addr, ret; 611 612 addr = icssg_queue_pop(prueth, slice == 0 ? 613 ICSSG_CMD_POP_SLICE0 : ICSSG_CMD_POP_SLICE1); 614 if (addr < 0) 615 return addr; 616 617 /* First 4 bytes have FW owned buffer linking info which should 618 * not be touched 619 */ 620 memcpy_toio(prueth->shram.va + addr + 4, cmd, sizeof(*cmd)); 621 icssg_queue_push(prueth, slice == 0 ? 622 ICSSG_CMD_PUSH_SLICE0 : ICSSG_CMD_PUSH_SLICE1, addr); 623 ret = read_poll_timeout(icssg_queue_pop, addr, addr >= 0, 624 2000, 20000000, false, prueth, slice == 0 ? 625 ICSSG_RSP_POP_SLICE0 : ICSSG_RSP_POP_SLICE1); 626 if (ret) { 627 netdev_err(emac->ndev, "Timedout sending HWQ message\n"); 628 return ret; 629 } 630 631 memcpy_fromio(rsp, prueth->shram.va + addr, sizeof(*rsp)); 632 /* Return buffer back for to pool */ 633 icssg_queue_push(prueth, slice == 0 ? 634 ICSSG_RSP_PUSH_SLICE0 : ICSSG_RSP_PUSH_SLICE1, addr); 635 636 return 0; 637 } 638 639 static void icssg_fdb_setup(struct prueth_emac *emac, struct mgmt_cmd *fdb_cmd, 640 const unsigned char *addr, u8 fid, int cmd) 641 { 642 int slice = prueth_emac_slice(emac); 643 u8 mac_fid[ETH_ALEN + 2]; 644 u16 fdb_slot; 645 646 ether_addr_copy(mac_fid, addr); 647 648 /* 1-1 VID-FID mapping is already setup */ 649 mac_fid[ETH_ALEN] = fid; 650 mac_fid[ETH_ALEN + 1] = 0; 651 652 fdb_slot = bitrev32(crc32_le(0, mac_fid, 8)) & PRUETH_SWITCH_FDB_MASK; 653 654 fdb_cmd->header = ICSSG_FW_MGMT_CMD_HEADER; 655 fdb_cmd->type = ICSSG_FW_MGMT_FDB_CMD_TYPE; 656 fdb_cmd->seqnum = ++(emac->prueth->icssg_hwcmdseq); 657 fdb_cmd->param = cmd; 658 fdb_cmd->param |= (slice << 4); 659 660 memcpy(&fdb_cmd->cmd_args[0], addr, 4); 661 memcpy(&fdb_cmd->cmd_args[1], &addr[4], 2); 662 fdb_cmd->cmd_args[2] = fdb_slot; 663 664 netdev_dbg(emac->ndev, "MAC %pM slot %X FID %X\n", addr, fdb_slot, fid); 665 } 666 667 int icssg_fdb_add_del(struct prueth_emac *emac, const unsigned char *addr, 668 u8 vid, u8 fid_c2, bool add) 669 { 670 struct mgmt_cmd_rsp fdb_cmd_rsp = { 0 }; 671 struct mgmt_cmd fdb_cmd = { 0 }; 672 u8 fid = vid; 673 int ret; 674 675 icssg_fdb_setup(emac, &fdb_cmd, addr, fid, add ? ICSS_CMD_ADD_FDB : ICSS_CMD_DEL_FDB); 676 677 fid_c2 |= ICSSG_FDB_ENTRY_VALID; 678 fdb_cmd.cmd_args[1] |= ((fid << 16) | (fid_c2 << 24)); 679 680 ret = icssg_send_fdb_msg(emac, &fdb_cmd, &fdb_cmd_rsp); 681 if (ret) 682 return ret; 683 684 WARN_ON(fdb_cmd.seqnum != fdb_cmd_rsp.seqnum); 685 if (fdb_cmd_rsp.status == 1) 686 return 0; 687 688 return -EINVAL; 689 } 690 691 int icssg_fdb_lookup(struct prueth_emac *emac, const unsigned char *addr, 692 u8 vid) 693 { 694 struct mgmt_cmd_rsp fdb_cmd_rsp = { 0 }; 695 struct mgmt_cmd fdb_cmd = { 0 }; 696 struct prueth_fdb_slot *slot; 697 u8 fid = vid; 698 int ret, i; 699 700 icssg_fdb_setup(emac, &fdb_cmd, addr, fid, ICSS_CMD_GET_FDB_SLOT); 701 702 fdb_cmd.cmd_args[1] |= fid << 16; 703 704 ret = icssg_send_fdb_msg(emac, &fdb_cmd, &fdb_cmd_rsp); 705 if (ret) 706 return ret; 707 708 WARN_ON(fdb_cmd.seqnum != fdb_cmd_rsp.seqnum); 709 710 slot = (struct prueth_fdb_slot __force *)(emac->dram.va + FDB_CMD_BUFFER); 711 for (i = 0; i < 4; i++) { 712 if (ether_addr_equal(addr, slot->mac) && vid == slot->fid) 713 return (slot->fid_c2 & ~ICSSG_FDB_ENTRY_VALID); 714 slot++; 715 } 716 717 return 0; 718 } 719 720 void icssg_vtbl_modify(struct prueth_emac *emac, u8 vid, u8 port_mask, 721 u8 untag_mask, bool add) 722 { 723 struct prueth *prueth = emac->prueth; 724 struct prueth_vlan_tbl *tbl; 725 u8 fid_c1; 726 727 tbl = prueth->vlan_tbl; 728 fid_c1 = tbl[vid].fid_c1; 729 730 /* FID_C1: bit0..2 port membership mask, 731 * bit3..5 tagging mask for each port 732 * bit6 Stream VID (not handled currently) 733 * bit7 MC flood (not handled currently) 734 */ 735 if (add) { 736 fid_c1 |= (port_mask | port_mask << 3); 737 fid_c1 &= ~(untag_mask << 3); 738 } else { 739 fid_c1 &= ~(port_mask | port_mask << 3); 740 } 741 742 tbl[vid].fid_c1 = fid_c1; 743 } 744 745 u16 icssg_get_pvid(struct prueth_emac *emac) 746 { 747 struct prueth *prueth = emac->prueth; 748 u32 pvid; 749 750 if (emac->port_id == PRUETH_PORT_MII0) 751 pvid = readl(prueth->shram.va + EMAC_ICSSG_SWITCH_PORT1_DEFAULT_VLAN_OFFSET); 752 else 753 pvid = readl(prueth->shram.va + EMAC_ICSSG_SWITCH_PORT2_DEFAULT_VLAN_OFFSET); 754 755 pvid = pvid >> 24; 756 757 return pvid; 758 } 759 760 void icssg_set_pvid(struct prueth *prueth, u8 vid, u8 port) 761 { 762 u32 pvid; 763 764 /* only 256 VLANs are supported */ 765 pvid = (u32 __force)cpu_to_be32((ETH_P_8021Q << 16) | (vid & 0xff)); 766 767 if (port == PRUETH_PORT_MII0) 768 writel(pvid, prueth->shram.va + EMAC_ICSSG_SWITCH_PORT1_DEFAULT_VLAN_OFFSET); 769 else if (port == PRUETH_PORT_MII1) 770 writel(pvid, prueth->shram.va + EMAC_ICSSG_SWITCH_PORT2_DEFAULT_VLAN_OFFSET); 771 else 772 writel(pvid, prueth->shram.va + EMAC_ICSSG_SWITCH_PORT0_DEFAULT_VLAN_OFFSET); 773 } 774