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(struct prueth_emac *emac) 111 { 112 u32 rxcfg, txcfg, rxcfg_reg, txcfg_reg, pcnt_reg; 113 struct prueth *prueth = emac->prueth; 114 int slice = prueth_emac_slice(emac); 115 struct regmap *mii_rt; 116 117 mii_rt = prueth->mii_rt; 118 119 rxcfg_reg = (slice == ICSS_MII0) ? PRUSS_MII_RT_RXCFG0 : 120 PRUSS_MII_RT_RXCFG1; 121 txcfg_reg = (slice == ICSS_MII0) ? PRUSS_MII_RT_TXCFG0 : 122 PRUSS_MII_RT_TXCFG1; 123 pcnt_reg = (slice == ICSS_MII0) ? PRUSS_MII_RT_RX_PCNT0 : 124 PRUSS_MII_RT_RX_PCNT1; 125 126 rxcfg = MII_RXCFG_DEFAULT; 127 txcfg = MII_TXCFG_DEFAULT; 128 129 if (slice == ICSS_MII1) 130 rxcfg |= PRUSS_MII_RT_RXCFG_RX_MUX_SEL; 131 132 /* In MII mode TX lines swapped inside ICSSG, so TX_MUX_SEL cfg need 133 * to be swapped also comparing to RGMII mode. 134 */ 135 if (emac->phy_if == PHY_INTERFACE_MODE_MII && slice == ICSS_MII0) 136 txcfg |= PRUSS_MII_RT_TXCFG_TX_MUX_SEL; 137 else if (emac->phy_if != PHY_INTERFACE_MODE_MII && slice == ICSS_MII1) 138 txcfg |= PRUSS_MII_RT_TXCFG_TX_MUX_SEL; 139 140 regmap_write(mii_rt, rxcfg_reg, rxcfg); 141 regmap_write(mii_rt, txcfg_reg, txcfg); 142 regmap_write(mii_rt, pcnt_reg, 0x1); 143 } 144 145 static void icssg_miig_queues_init(struct prueth *prueth, int slice) 146 { 147 struct regmap *miig_rt = prueth->miig_rt; 148 void __iomem *smem = prueth->shram.va; 149 u8 pd[ICSSG_SPECIAL_PD_SIZE]; 150 int queue = 0, i, j; 151 u32 *pdword; 152 153 /* reset hwqueues */ 154 if (slice) 155 queue = ICSSG_NUM_TX_QUEUES; 156 157 for (i = 0; i < ICSSG_NUM_TX_QUEUES; i++) { 158 regmap_write(miig_rt, ICSSG_QUEUE_RESET_OFFSET, queue); 159 queue++; 160 } 161 162 queue = slice ? RECYCLE_Q_SLICE1 : RECYCLE_Q_SLICE0; 163 regmap_write(miig_rt, ICSSG_QUEUE_RESET_OFFSET, queue); 164 165 for (i = 0; i < ICSSG_NUM_OTHER_QUEUES; i++) { 166 regmap_write(miig_rt, ICSSG_QUEUE_RESET_OFFSET, 167 hwq_map[slice][i].queue); 168 } 169 170 /* initialize packet descriptors in SMEM */ 171 /* push pakcet descriptors to hwqueues */ 172 173 pdword = (u32 *)pd; 174 for (j = 0; j < ICSSG_NUM_OTHER_QUEUES; j++) { 175 const struct map *mp; 176 int pd_size, num_pds; 177 u32 pdaddr; 178 179 mp = &hwq_map[slice][j]; 180 if (mp->special) { 181 pd_size = ICSSG_SPECIAL_PD_SIZE; 182 num_pds = ICSSG_NUM_SPECIAL_PDS; 183 } else { 184 pd_size = ICSSG_NORMAL_PD_SIZE; 185 num_pds = ICSSG_NUM_NORMAL_PDS; 186 } 187 188 for (i = 0; i < num_pds; i++) { 189 memset(pd, 0, pd_size); 190 191 pdword[0] &= ICSSG_FLAG_MASK; 192 pdword[0] |= mp->flags; 193 pdaddr = mp->pd_addr_start + i * pd_size; 194 195 memcpy_toio(smem + pdaddr, pd, pd_size); 196 queue = mp->queue; 197 regmap_write(miig_rt, ICSSG_QUEUE_OFFSET + 4 * queue, 198 pdaddr); 199 } 200 } 201 } 202 203 void icssg_config_ipg(struct prueth_emac *emac) 204 { 205 struct prueth *prueth = emac->prueth; 206 int slice = prueth_emac_slice(emac); 207 u32 ipg; 208 209 switch (emac->speed) { 210 case SPEED_1000: 211 ipg = emac->is_sr1 ? MII_RT_TX_IPG_1G_SR1 : MII_RT_TX_IPG_1G; 212 break; 213 case SPEED_100: 214 ipg = emac->is_sr1 ? MII_RT_TX_IPG_100M_SR1 : MII_RT_TX_IPG_100M; 215 break; 216 case SPEED_10: 217 /* Firmware hardcodes IPG for SR1.0 */ 218 if (emac->is_sr1) 219 return; 220 /* IPG for 10M is same as 100M */ 221 ipg = MII_RT_TX_IPG_100M; 222 break; 223 default: 224 /* Other links speeds not supported */ 225 netdev_err(emac->ndev, "Unsupported link speed\n"); 226 return; 227 } 228 229 icssg_mii_update_ipg(prueth->mii_rt, slice, ipg); 230 } 231 232 static void emac_r30_cmd_init(struct prueth_emac *emac) 233 { 234 struct icssg_r30_cmd __iomem *p; 235 int i; 236 237 p = emac->dram.va + MGR_R30_CMD_OFFSET; 238 239 for (i = 0; i < 4; i++) 240 writel(EMAC_NONE, &p->cmd[i]); 241 } 242 243 static int emac_r30_is_done(struct prueth_emac *emac) 244 { 245 const struct icssg_r30_cmd __iomem *p; 246 u32 cmd; 247 int i; 248 249 p = emac->dram.va + MGR_R30_CMD_OFFSET; 250 251 for (i = 0; i < 4; i++) { 252 cmd = readl(&p->cmd[i]); 253 if (cmd != EMAC_NONE) 254 return 0; 255 } 256 257 return 1; 258 } 259 260 static int prueth_emac_buffer_setup(struct prueth_emac *emac) 261 { 262 struct icssg_buffer_pool_cfg __iomem *bpool_cfg; 263 struct icssg_rxq_ctx __iomem *rxq_ctx; 264 struct prueth *prueth = emac->prueth; 265 int slice = prueth_emac_slice(emac); 266 u32 addr; 267 int i; 268 269 /* Layout to have 64KB aligned buffer pool 270 * |BPOOL0|BPOOL1|RX_CTX0|RX_CTX1| 271 */ 272 273 addr = lower_32_bits(prueth->msmcram.pa); 274 if (slice) 275 addr += PRUETH_NUM_BUF_POOLS * PRUETH_EMAC_BUF_POOL_SIZE; 276 277 if (addr % SZ_64K) { 278 dev_warn(prueth->dev, "buffer pool needs to be 64KB aligned\n"); 279 return -EINVAL; 280 } 281 282 bpool_cfg = emac->dram.va + BUFFER_POOL_0_ADDR_OFFSET; 283 /* workaround for f/w bug. bpool 0 needs to be initilalized */ 284 writel(addr, &bpool_cfg[0].addr); 285 writel(0, &bpool_cfg[0].len); 286 287 for (i = PRUETH_EMAC_BUF_POOL_START; 288 i < PRUETH_EMAC_BUF_POOL_START + PRUETH_NUM_BUF_POOLS; 289 i++) { 290 writel(addr, &bpool_cfg[i].addr); 291 writel(PRUETH_EMAC_BUF_POOL_SIZE, &bpool_cfg[i].len); 292 addr += PRUETH_EMAC_BUF_POOL_SIZE; 293 } 294 295 if (!slice) 296 addr += PRUETH_NUM_BUF_POOLS * PRUETH_EMAC_BUF_POOL_SIZE; 297 else 298 addr += PRUETH_EMAC_RX_CTX_BUF_SIZE * 2; 299 300 /* Pre-emptible RX buffer queue */ 301 rxq_ctx = emac->dram.va + HOST_RX_Q_PRE_CONTEXT_OFFSET; 302 for (i = 0; i < 3; i++) 303 writel(addr, &rxq_ctx->start[i]); 304 305 addr += PRUETH_EMAC_RX_CTX_BUF_SIZE; 306 writel(addr, &rxq_ctx->end); 307 308 /* Express RX buffer queue */ 309 rxq_ctx = emac->dram.va + HOST_RX_Q_EXP_CONTEXT_OFFSET; 310 for (i = 0; i < 3; i++) 311 writel(addr, &rxq_ctx->start[i]); 312 313 addr += PRUETH_EMAC_RX_CTX_BUF_SIZE; 314 writel(addr, &rxq_ctx->end); 315 316 return 0; 317 } 318 319 static void icssg_init_emac_mode(struct prueth *prueth) 320 { 321 /* When the device is configured as a bridge and it is being brought 322 * back to the emac mode, the host mac address has to be set as 0. 323 */ 324 u8 mac[ETH_ALEN] = { 0 }; 325 326 if (prueth->emacs_initialized) 327 return; 328 329 regmap_update_bits(prueth->miig_rt, FDB_GEN_CFG1, 330 SMEM_VLAN_OFFSET_MASK, 0); 331 regmap_write(prueth->miig_rt, FDB_GEN_CFG2, 0); 332 /* Clear host MAC address */ 333 icssg_class_set_host_mac_addr(prueth->miig_rt, mac); 334 } 335 336 int icssg_config(struct prueth *prueth, struct prueth_emac *emac, int slice) 337 { 338 void __iomem *config = emac->dram.va + ICSSG_CONFIG_OFFSET; 339 struct icssg_flow_cfg __iomem *flow_cfg; 340 int ret; 341 342 icssg_init_emac_mode(prueth); 343 344 memset_io(config, 0, TAS_GATE_MASK_LIST0); 345 icssg_miig_queues_init(prueth, slice); 346 347 emac->speed = SPEED_1000; 348 emac->duplex = DUPLEX_FULL; 349 if (!phy_interface_mode_is_rgmii(emac->phy_if)) { 350 emac->speed = SPEED_100; 351 emac->duplex = DUPLEX_FULL; 352 } 353 regmap_update_bits(prueth->miig_rt, ICSSG_CFG_OFFSET, 354 ICSSG_CFG_DEFAULT, ICSSG_CFG_DEFAULT); 355 icssg_miig_set_interface_mode(prueth->miig_rt, slice, emac->phy_if); 356 icssg_config_mii_init(emac); 357 icssg_config_ipg(emac); 358 icssg_update_rgmii_cfg(prueth->miig_rt, emac); 359 360 /* set GPI mode */ 361 pruss_cfg_gpimode(prueth->pruss, prueth->pru_id[slice], 362 PRUSS_GPI_MODE_MII); 363 364 /* enable XFR shift for PRU and RTU */ 365 pruss_cfg_xfr_enable(prueth->pruss, PRU_TYPE_PRU, true); 366 pruss_cfg_xfr_enable(prueth->pruss, PRU_TYPE_RTU, true); 367 368 /* set C28 to 0x100 */ 369 pru_rproc_set_ctable(prueth->pru[slice], PRU_C28, 0x100 << 8); 370 pru_rproc_set_ctable(prueth->rtu[slice], PRU_C28, 0x100 << 8); 371 pru_rproc_set_ctable(prueth->txpru[slice], PRU_C28, 0x100 << 8); 372 373 flow_cfg = config + PSI_L_REGULAR_FLOW_ID_BASE_OFFSET; 374 writew(emac->rx_flow_id_base, &flow_cfg->rx_base_flow); 375 writew(0, &flow_cfg->mgm_base_flow); 376 writeb(0, config + SPL_PKT_DEFAULT_PRIORITY); 377 writeb(0, config + QUEUE_NUM_UNTAGGED); 378 379 ret = prueth_emac_buffer_setup(emac); 380 if (ret) 381 return ret; 382 383 emac_r30_cmd_init(emac); 384 385 return 0; 386 } 387 388 /* Bitmask for ICSSG r30 commands */ 389 static const struct icssg_r30_cmd emac_r32_bitmask[] = { 390 {{0xffff0004, 0xffff0100, 0xffff0004, EMAC_NONE}}, /* EMAC_PORT_DISABLE */ 391 {{0xfffb0040, 0xfeff0200, 0xfeff0200, EMAC_NONE}}, /* EMAC_PORT_BLOCK */ 392 {{0xffbb0000, 0xfcff0000, 0xdcfb0000, EMAC_NONE}}, /* EMAC_PORT_FORWARD */ 393 {{0xffbb0000, 0xfcff0000, 0xfcff2000, EMAC_NONE}}, /* EMAC_PORT_FORWARD_WO_LEARNING */ 394 {{0xffff0001, EMAC_NONE, EMAC_NONE, EMAC_NONE}}, /* ACCEPT ALL */ 395 {{0xfffe0002, EMAC_NONE, EMAC_NONE, EMAC_NONE}}, /* ACCEPT TAGGED */ 396 {{0xfffc0000, EMAC_NONE, EMAC_NONE, EMAC_NONE}}, /* ACCEPT UNTAGGED and PRIO */ 397 {{EMAC_NONE, 0xffff0020, EMAC_NONE, EMAC_NONE}}, /* TAS Trigger List change */ 398 {{EMAC_NONE, 0xdfff1000, EMAC_NONE, EMAC_NONE}}, /* TAS set state ENABLE*/ 399 {{EMAC_NONE, 0xefff2000, EMAC_NONE, EMAC_NONE}}, /* TAS set state RESET*/ 400 {{EMAC_NONE, 0xcfff0000, EMAC_NONE, EMAC_NONE}}, /* TAS set state DISABLE*/ 401 {{EMAC_NONE, EMAC_NONE, 0xffff0400, EMAC_NONE}}, /* UC flooding ENABLE*/ 402 {{EMAC_NONE, EMAC_NONE, 0xfbff0000, EMAC_NONE}}, /* UC flooding DISABLE*/ 403 {{EMAC_NONE, EMAC_NONE, 0xffff0800, EMAC_NONE}}, /* MC flooding ENABLE*/ 404 {{EMAC_NONE, EMAC_NONE, 0xf7ff0000, EMAC_NONE}}, /* MC flooding DISABLE*/ 405 {{EMAC_NONE, 0xffff4000, EMAC_NONE, EMAC_NONE}}, /* Preemption on Tx ENABLE*/ 406 {{EMAC_NONE, 0xbfff0000, EMAC_NONE, EMAC_NONE}}, /* Preemption on Tx DISABLE*/ 407 {{0xffff0010, EMAC_NONE, 0xffff0010, EMAC_NONE}}, /* VLAN AWARE*/ 408 {{0xffef0000, EMAC_NONE, 0xffef0000, EMAC_NONE}} /* VLAN UNWARE*/ 409 }; 410 411 int emac_set_port_state(struct prueth_emac *emac, 412 enum icssg_port_state_cmd cmd) 413 { 414 struct icssg_r30_cmd __iomem *p; 415 int ret = -ETIMEDOUT; 416 int done = 0; 417 int i; 418 419 p = emac->dram.va + MGR_R30_CMD_OFFSET; 420 421 if (cmd >= ICSSG_EMAC_PORT_MAX_COMMANDS) { 422 netdev_err(emac->ndev, "invalid port command\n"); 423 return -EINVAL; 424 } 425 426 /* only one command at a time allowed to firmware */ 427 mutex_lock(&emac->cmd_lock); 428 429 for (i = 0; i < 4; i++) 430 writel(emac_r32_bitmask[cmd].cmd[i], &p->cmd[i]); 431 432 /* wait for done */ 433 ret = read_poll_timeout(emac_r30_is_done, done, done == 1, 434 1000, 10000, false, emac); 435 436 if (ret == -ETIMEDOUT) 437 netdev_err(emac->ndev, "timeout waiting for command done\n"); 438 439 mutex_unlock(&emac->cmd_lock); 440 441 return ret; 442 } 443 444 void icssg_config_half_duplex(struct prueth_emac *emac) 445 { 446 u32 val; 447 448 if (!emac->half_duplex) 449 return; 450 451 val = get_random_u32(); 452 writel(val, emac->dram.va + HD_RAND_SEED_OFFSET); 453 } 454 455 void icssg_config_set_speed(struct prueth_emac *emac) 456 { 457 u8 fw_speed; 458 459 switch (emac->speed) { 460 case SPEED_1000: 461 fw_speed = FW_LINK_SPEED_1G; 462 break; 463 case SPEED_100: 464 fw_speed = FW_LINK_SPEED_100M; 465 break; 466 case SPEED_10: 467 fw_speed = FW_LINK_SPEED_10M; 468 break; 469 default: 470 /* Other links speeds not supported */ 471 netdev_err(emac->ndev, "Unsupported link speed\n"); 472 return; 473 } 474 475 if (emac->duplex == DUPLEX_HALF) 476 fw_speed |= FW_LINK_SPEED_HD; 477 478 writeb(fw_speed, emac->dram.va + PORT_LINK_SPEED_OFFSET); 479 } 480