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 24 #define ICSSG_QUEUES_MAX 64 25 #define ICSSG_QUEUE_OFFSET 0xd00 26 #define ICSSG_QUEUE_PEEK_OFFSET 0xe00 27 #define ICSSG_QUEUE_CNT_OFFSET 0xe40 28 #define ICSSG_QUEUE_RESET_OFFSET 0xf40 29 30 #define ICSSG_NUM_TX_QUEUES 8 31 32 #define RECYCLE_Q_SLICE0 16 33 #define RECYCLE_Q_SLICE1 17 34 35 #define ICSSG_NUM_OTHER_QUEUES 5 /* port, host and special queues */ 36 37 #define PORT_HI_Q_SLICE0 32 38 #define PORT_LO_Q_SLICE0 33 39 #define HOST_HI_Q_SLICE0 34 40 #define HOST_LO_Q_SLICE0 35 41 #define HOST_SPL_Q_SLICE0 40 /* Special Queue */ 42 43 #define PORT_HI_Q_SLICE1 36 44 #define PORT_LO_Q_SLICE1 37 45 #define HOST_HI_Q_SLICE1 38 46 #define HOST_LO_Q_SLICE1 39 47 #define HOST_SPL_Q_SLICE1 41 /* Special Queue */ 48 49 #define MII_RXCFG_DEFAULT (PRUSS_MII_RT_RXCFG_RX_ENABLE | \ 50 PRUSS_MII_RT_RXCFG_RX_DATA_RDY_MODE_DIS | \ 51 PRUSS_MII_RT_RXCFG_RX_L2_EN | \ 52 PRUSS_MII_RT_RXCFG_RX_L2_EOF_SCLR_DIS) 53 54 #define MII_TXCFG_DEFAULT (PRUSS_MII_RT_TXCFG_TX_ENABLE | \ 55 PRUSS_MII_RT_TXCFG_TX_AUTO_PREAMBLE | \ 56 PRUSS_MII_RT_TXCFG_TX_32_MODE_EN | \ 57 PRUSS_MII_RT_TXCFG_TX_IPG_WIRE_CLK_EN) 58 59 #define ICSSG_CFG_DEFAULT (ICSSG_CFG_TX_L1_EN | \ 60 ICSSG_CFG_TX_L2_EN | ICSSG_CFG_RX_L2_G_EN | \ 61 ICSSG_CFG_TX_PRU_EN | \ 62 ICSSG_CFG_SGMII_MODE) 63 64 #define FDB_GEN_CFG1 0x60 65 #define SMEM_VLAN_OFFSET 8 66 #define SMEM_VLAN_OFFSET_MASK GENMASK(25, 8) 67 68 #define FDB_GEN_CFG2 0x64 69 #define FDB_VLAN_EN BIT(6) 70 #define FDB_HOST_EN BIT(2) 71 #define FDB_PRU1_EN BIT(1) 72 #define FDB_PRU0_EN BIT(0) 73 #define FDB_EN_ALL (FDB_PRU0_EN | FDB_PRU1_EN | \ 74 FDB_HOST_EN | FDB_VLAN_EN) 75 76 /** 77 * struct map - ICSSG Queue Map 78 * @queue: Queue number 79 * @pd_addr_start: Packet descriptor queue reserved memory 80 * @flags: Flags 81 * @special: Indicates whether this queue is a special queue or not 82 */ 83 struct map { 84 int queue; 85 u32 pd_addr_start; 86 u32 flags; 87 bool special; 88 }; 89 90 /* Hardware queue map for ICSSG */ 91 static const struct map hwq_map[2][ICSSG_NUM_OTHER_QUEUES] = { 92 { 93 { PORT_HI_Q_SLICE0, PORT_DESC0_HI, 0x200000, 0 }, 94 { PORT_LO_Q_SLICE0, PORT_DESC0_LO, 0, 0 }, 95 { HOST_HI_Q_SLICE0, HOST_DESC0_HI, 0x200000, 0 }, 96 { HOST_LO_Q_SLICE0, HOST_DESC0_LO, 0, 0 }, 97 { HOST_SPL_Q_SLICE0, HOST_SPPD0, 0x400000, 1 }, 98 }, 99 { 100 { PORT_HI_Q_SLICE1, PORT_DESC1_HI, 0xa00000, 0 }, 101 { PORT_LO_Q_SLICE1, PORT_DESC1_LO, 0x800000, 0 }, 102 { HOST_HI_Q_SLICE1, HOST_DESC1_HI, 0xa00000, 0 }, 103 { HOST_LO_Q_SLICE1, HOST_DESC1_LO, 0x800000, 0 }, 104 { HOST_SPL_Q_SLICE1, HOST_SPPD1, 0xc00000, 1 }, 105 }, 106 }; 107 108 static void icssg_config_mii_init(struct prueth_emac *emac) 109 { 110 u32 rxcfg, txcfg, rxcfg_reg, txcfg_reg, pcnt_reg; 111 struct prueth *prueth = emac->prueth; 112 int slice = prueth_emac_slice(emac); 113 struct regmap *mii_rt; 114 115 mii_rt = prueth->mii_rt; 116 117 rxcfg_reg = (slice == ICSS_MII0) ? PRUSS_MII_RT_RXCFG0 : 118 PRUSS_MII_RT_RXCFG1; 119 txcfg_reg = (slice == ICSS_MII0) ? PRUSS_MII_RT_TXCFG0 : 120 PRUSS_MII_RT_TXCFG1; 121 pcnt_reg = (slice == ICSS_MII0) ? PRUSS_MII_RT_RX_PCNT0 : 122 PRUSS_MII_RT_RX_PCNT1; 123 124 rxcfg = MII_RXCFG_DEFAULT; 125 txcfg = MII_TXCFG_DEFAULT; 126 127 if (slice == ICSS_MII1) 128 rxcfg |= PRUSS_MII_RT_RXCFG_RX_MUX_SEL; 129 130 /* In MII mode TX lines swapped inside ICSSG, so TX_MUX_SEL cfg need 131 * to be swapped also comparing to RGMII mode. 132 */ 133 if (emac->phy_if == PHY_INTERFACE_MODE_MII && slice == ICSS_MII0) 134 txcfg |= PRUSS_MII_RT_TXCFG_TX_MUX_SEL; 135 else if (emac->phy_if != PHY_INTERFACE_MODE_MII && slice == ICSS_MII1) 136 txcfg |= PRUSS_MII_RT_TXCFG_TX_MUX_SEL; 137 138 regmap_write(mii_rt, rxcfg_reg, rxcfg); 139 regmap_write(mii_rt, txcfg_reg, txcfg); 140 regmap_write(mii_rt, pcnt_reg, 0x1); 141 } 142 143 static void icssg_miig_queues_init(struct prueth *prueth, int slice) 144 { 145 struct regmap *miig_rt = prueth->miig_rt; 146 void __iomem *smem = prueth->shram.va; 147 u8 pd[ICSSG_SPECIAL_PD_SIZE]; 148 int queue = 0, i, j; 149 u32 *pdword; 150 151 /* reset hwqueues */ 152 if (slice) 153 queue = ICSSG_NUM_TX_QUEUES; 154 155 for (i = 0; i < ICSSG_NUM_TX_QUEUES; i++) { 156 regmap_write(miig_rt, ICSSG_QUEUE_RESET_OFFSET, queue); 157 queue++; 158 } 159 160 queue = slice ? RECYCLE_Q_SLICE1 : RECYCLE_Q_SLICE0; 161 regmap_write(miig_rt, ICSSG_QUEUE_RESET_OFFSET, queue); 162 163 for (i = 0; i < ICSSG_NUM_OTHER_QUEUES; i++) { 164 regmap_write(miig_rt, ICSSG_QUEUE_RESET_OFFSET, 165 hwq_map[slice][i].queue); 166 } 167 168 /* initialize packet descriptors in SMEM */ 169 /* push pakcet descriptors to hwqueues */ 170 171 pdword = (u32 *)pd; 172 for (j = 0; j < ICSSG_NUM_OTHER_QUEUES; j++) { 173 const struct map *mp; 174 int pd_size, num_pds; 175 u32 pdaddr; 176 177 mp = &hwq_map[slice][j]; 178 if (mp->special) { 179 pd_size = ICSSG_SPECIAL_PD_SIZE; 180 num_pds = ICSSG_NUM_SPECIAL_PDS; 181 } else { 182 pd_size = ICSSG_NORMAL_PD_SIZE; 183 num_pds = ICSSG_NUM_NORMAL_PDS; 184 } 185 186 for (i = 0; i < num_pds; i++) { 187 memset(pd, 0, pd_size); 188 189 pdword[0] &= ICSSG_FLAG_MASK; 190 pdword[0] |= mp->flags; 191 pdaddr = mp->pd_addr_start + i * pd_size; 192 193 memcpy_toio(smem + pdaddr, pd, pd_size); 194 queue = mp->queue; 195 regmap_write(miig_rt, ICSSG_QUEUE_OFFSET + 4 * queue, 196 pdaddr); 197 } 198 } 199 } 200 201 void icssg_config_ipg(struct prueth_emac *emac) 202 { 203 struct prueth *prueth = emac->prueth; 204 int slice = prueth_emac_slice(emac); 205 206 switch (emac->speed) { 207 case SPEED_1000: 208 icssg_mii_update_ipg(prueth->mii_rt, slice, MII_RT_TX_IPG_1G); 209 break; 210 case SPEED_100: 211 icssg_mii_update_ipg(prueth->mii_rt, slice, MII_RT_TX_IPG_100M); 212 break; 213 case SPEED_10: 214 /* IPG for 10M is same as 100M */ 215 icssg_mii_update_ipg(prueth->mii_rt, slice, MII_RT_TX_IPG_100M); 216 break; 217 default: 218 /* Other links speeds not supported */ 219 netdev_err(emac->ndev, "Unsupported link speed\n"); 220 return; 221 } 222 } 223 224 static void emac_r30_cmd_init(struct prueth_emac *emac) 225 { 226 struct icssg_r30_cmd __iomem *p; 227 int i; 228 229 p = emac->dram.va + MGR_R30_CMD_OFFSET; 230 231 for (i = 0; i < 4; i++) 232 writel(EMAC_NONE, &p->cmd[i]); 233 } 234 235 static int emac_r30_is_done(struct prueth_emac *emac) 236 { 237 const struct icssg_r30_cmd __iomem *p; 238 u32 cmd; 239 int i; 240 241 p = emac->dram.va + MGR_R30_CMD_OFFSET; 242 243 for (i = 0; i < 4; i++) { 244 cmd = readl(&p->cmd[i]); 245 if (cmd != EMAC_NONE) 246 return 0; 247 } 248 249 return 1; 250 } 251 252 static int prueth_emac_buffer_setup(struct prueth_emac *emac) 253 { 254 struct icssg_buffer_pool_cfg __iomem *bpool_cfg; 255 struct icssg_rxq_ctx __iomem *rxq_ctx; 256 struct prueth *prueth = emac->prueth; 257 int slice = prueth_emac_slice(emac); 258 u32 addr; 259 int i; 260 261 /* Layout to have 64KB aligned buffer pool 262 * |BPOOL0|BPOOL1|RX_CTX0|RX_CTX1| 263 */ 264 265 addr = lower_32_bits(prueth->msmcram.pa); 266 if (slice) 267 addr += PRUETH_NUM_BUF_POOLS * PRUETH_EMAC_BUF_POOL_SIZE; 268 269 if (addr % SZ_64K) { 270 dev_warn(prueth->dev, "buffer pool needs to be 64KB aligned\n"); 271 return -EINVAL; 272 } 273 274 bpool_cfg = emac->dram.va + BUFFER_POOL_0_ADDR_OFFSET; 275 /* workaround for f/w bug. bpool 0 needs to be initilalized */ 276 writel(addr, &bpool_cfg[0].addr); 277 writel(0, &bpool_cfg[0].len); 278 279 for (i = PRUETH_EMAC_BUF_POOL_START; 280 i < PRUETH_EMAC_BUF_POOL_START + PRUETH_NUM_BUF_POOLS; 281 i++) { 282 writel(addr, &bpool_cfg[i].addr); 283 writel(PRUETH_EMAC_BUF_POOL_SIZE, &bpool_cfg[i].len); 284 addr += PRUETH_EMAC_BUF_POOL_SIZE; 285 } 286 287 if (!slice) 288 addr += PRUETH_NUM_BUF_POOLS * PRUETH_EMAC_BUF_POOL_SIZE; 289 else 290 addr += PRUETH_EMAC_RX_CTX_BUF_SIZE * 2; 291 292 /* Pre-emptible RX buffer queue */ 293 rxq_ctx = emac->dram.va + HOST_RX_Q_PRE_CONTEXT_OFFSET; 294 for (i = 0; i < 3; i++) 295 writel(addr, &rxq_ctx->start[i]); 296 297 addr += PRUETH_EMAC_RX_CTX_BUF_SIZE; 298 writel(addr, &rxq_ctx->end); 299 300 /* Express RX buffer queue */ 301 rxq_ctx = emac->dram.va + HOST_RX_Q_EXP_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 return 0; 309 } 310 311 static void icssg_init_emac_mode(struct prueth *prueth) 312 { 313 /* When the device is configured as a bridge and it is being brought 314 * back to the emac mode, the host mac address has to be set as 0. 315 */ 316 u8 mac[ETH_ALEN] = { 0 }; 317 318 if (prueth->emacs_initialized) 319 return; 320 321 regmap_update_bits(prueth->miig_rt, FDB_GEN_CFG1, 322 SMEM_VLAN_OFFSET_MASK, 0); 323 regmap_write(prueth->miig_rt, FDB_GEN_CFG2, 0); 324 /* Clear host MAC address */ 325 icssg_class_set_host_mac_addr(prueth->miig_rt, mac); 326 } 327 328 int icssg_config(struct prueth *prueth, struct prueth_emac *emac, int slice) 329 { 330 void __iomem *config = emac->dram.va + ICSSG_CONFIG_OFFSET; 331 struct icssg_flow_cfg __iomem *flow_cfg; 332 int ret; 333 334 icssg_init_emac_mode(prueth); 335 336 memset_io(config, 0, TAS_GATE_MASK_LIST0); 337 icssg_miig_queues_init(prueth, slice); 338 339 emac->speed = SPEED_1000; 340 emac->duplex = DUPLEX_FULL; 341 if (!phy_interface_mode_is_rgmii(emac->phy_if)) { 342 emac->speed = SPEED_100; 343 emac->duplex = DUPLEX_FULL; 344 } 345 regmap_update_bits(prueth->miig_rt, ICSSG_CFG_OFFSET, 346 ICSSG_CFG_DEFAULT, ICSSG_CFG_DEFAULT); 347 icssg_miig_set_interface_mode(prueth->miig_rt, slice, emac->phy_if); 348 icssg_config_mii_init(emac); 349 icssg_config_ipg(emac); 350 icssg_update_rgmii_cfg(prueth->miig_rt, emac); 351 352 /* set GPI mode */ 353 pruss_cfg_gpimode(prueth->pruss, prueth->pru_id[slice], 354 PRUSS_GPI_MODE_MII); 355 356 /* enable XFR shift for PRU and RTU */ 357 pruss_cfg_xfr_enable(prueth->pruss, PRU_TYPE_PRU, true); 358 pruss_cfg_xfr_enable(prueth->pruss, PRU_TYPE_RTU, true); 359 360 /* set C28 to 0x100 */ 361 pru_rproc_set_ctable(prueth->pru[slice], PRU_C28, 0x100 << 8); 362 pru_rproc_set_ctable(prueth->rtu[slice], PRU_C28, 0x100 << 8); 363 pru_rproc_set_ctable(prueth->txpru[slice], PRU_C28, 0x100 << 8); 364 365 flow_cfg = config + PSI_L_REGULAR_FLOW_ID_BASE_OFFSET; 366 writew(emac->rx_flow_id_base, &flow_cfg->rx_base_flow); 367 writew(0, &flow_cfg->mgm_base_flow); 368 writeb(0, config + SPL_PKT_DEFAULT_PRIORITY); 369 writeb(0, config + QUEUE_NUM_UNTAGGED); 370 371 ret = prueth_emac_buffer_setup(emac); 372 if (ret) 373 return ret; 374 375 emac_r30_cmd_init(emac); 376 377 return 0; 378 } 379 380 /* Bitmask for ICSSG r30 commands */ 381 static const struct icssg_r30_cmd emac_r32_bitmask[] = { 382 {{0xffff0004, 0xffff0100, 0xffff0100, EMAC_NONE}}, /* EMAC_PORT_DISABLE */ 383 {{0xfffb0040, 0xfeff0200, 0xfeff0200, EMAC_NONE}}, /* EMAC_PORT_BLOCK */ 384 {{0xffbb0000, 0xfcff0000, 0xdcff0000, EMAC_NONE}}, /* EMAC_PORT_FORWARD */ 385 {{0xffbb0000, 0xfcff0000, 0xfcff2000, EMAC_NONE}}, /* EMAC_PORT_FORWARD_WO_LEARNING */ 386 {{0xffff0001, EMAC_NONE, EMAC_NONE, EMAC_NONE}}, /* ACCEPT ALL */ 387 {{0xfffe0002, EMAC_NONE, EMAC_NONE, EMAC_NONE}}, /* ACCEPT TAGGED */ 388 {{0xfffc0000, EMAC_NONE, EMAC_NONE, EMAC_NONE}}, /* ACCEPT UNTAGGED and PRIO */ 389 {{EMAC_NONE, 0xffff0020, EMAC_NONE, EMAC_NONE}}, /* TAS Trigger List change */ 390 {{EMAC_NONE, 0xdfff1000, EMAC_NONE, EMAC_NONE}}, /* TAS set state ENABLE*/ 391 {{EMAC_NONE, 0xefff2000, EMAC_NONE, EMAC_NONE}}, /* TAS set state RESET*/ 392 {{EMAC_NONE, 0xcfff0000, EMAC_NONE, EMAC_NONE}}, /* TAS set state DISABLE*/ 393 {{EMAC_NONE, EMAC_NONE, 0xffff0400, EMAC_NONE}}, /* UC flooding ENABLE*/ 394 {{EMAC_NONE, EMAC_NONE, 0xfbff0000, EMAC_NONE}}, /* UC flooding DISABLE*/ 395 {{EMAC_NONE, EMAC_NONE, 0xffff0800, EMAC_NONE}}, /* MC flooding ENABLE*/ 396 {{EMAC_NONE, EMAC_NONE, 0xf7ff0000, EMAC_NONE}}, /* MC flooding DISABLE*/ 397 {{EMAC_NONE, 0xffff4000, EMAC_NONE, EMAC_NONE}}, /* Preemption on Tx ENABLE*/ 398 {{EMAC_NONE, 0xbfff0000, EMAC_NONE, EMAC_NONE}}, /* Preemption on Tx DISABLE*/ 399 {{0xffff0010, EMAC_NONE, 0xffff0010, EMAC_NONE}}, /* VLAN AWARE*/ 400 {{0xffef0000, EMAC_NONE, 0xffef0000, EMAC_NONE}} /* VLAN UNWARE*/ 401 }; 402 403 int emac_set_port_state(struct prueth_emac *emac, 404 enum icssg_port_state_cmd cmd) 405 { 406 struct icssg_r30_cmd __iomem *p; 407 int ret = -ETIMEDOUT; 408 int done = 0; 409 int i; 410 411 p = emac->dram.va + MGR_R30_CMD_OFFSET; 412 413 if (cmd >= ICSSG_EMAC_PORT_MAX_COMMANDS) { 414 netdev_err(emac->ndev, "invalid port command\n"); 415 return -EINVAL; 416 } 417 418 /* only one command at a time allowed to firmware */ 419 mutex_lock(&emac->cmd_lock); 420 421 for (i = 0; i < 4; i++) 422 writel(emac_r32_bitmask[cmd].cmd[i], &p->cmd[i]); 423 424 /* wait for done */ 425 ret = read_poll_timeout(emac_r30_is_done, done, done == 1, 426 1000, 10000, false, emac); 427 428 if (ret == -ETIMEDOUT) 429 netdev_err(emac->ndev, "timeout waiting for command done\n"); 430 431 mutex_unlock(&emac->cmd_lock); 432 433 return ret; 434 } 435 436 void icssg_config_set_speed(struct prueth_emac *emac) 437 { 438 u8 fw_speed; 439 440 switch (emac->speed) { 441 case SPEED_1000: 442 fw_speed = FW_LINK_SPEED_1G; 443 break; 444 case SPEED_100: 445 fw_speed = FW_LINK_SPEED_100M; 446 break; 447 case SPEED_10: 448 fw_speed = FW_LINK_SPEED_10M; 449 break; 450 default: 451 /* Other links speeds not supported */ 452 netdev_err(emac->ndev, "Unsupported link speed\n"); 453 return; 454 } 455 456 writeb(fw_speed, emac->dram.va + PORT_LINK_SPEED_OFFSET); 457 } 458