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 default: 214 /* Other links speeds not supported */ 215 netdev_err(emac->ndev, "Unsupported link speed\n"); 216 return; 217 } 218 } 219 220 static void emac_r30_cmd_init(struct prueth_emac *emac) 221 { 222 struct icssg_r30_cmd __iomem *p; 223 int i; 224 225 p = emac->dram.va + MGR_R30_CMD_OFFSET; 226 227 for (i = 0; i < 4; i++) 228 writel(EMAC_NONE, &p->cmd[i]); 229 } 230 231 static int emac_r30_is_done(struct prueth_emac *emac) 232 { 233 const struct icssg_r30_cmd __iomem *p; 234 u32 cmd; 235 int i; 236 237 p = emac->dram.va + MGR_R30_CMD_OFFSET; 238 239 for (i = 0; i < 4; i++) { 240 cmd = readl(&p->cmd[i]); 241 if (cmd != EMAC_NONE) 242 return 0; 243 } 244 245 return 1; 246 } 247 248 static int prueth_emac_buffer_setup(struct prueth_emac *emac) 249 { 250 struct icssg_buffer_pool_cfg __iomem *bpool_cfg; 251 struct icssg_rxq_ctx __iomem *rxq_ctx; 252 struct prueth *prueth = emac->prueth; 253 int slice = prueth_emac_slice(emac); 254 u32 addr; 255 int i; 256 257 /* Layout to have 64KB aligned buffer pool 258 * |BPOOL0|BPOOL1|RX_CTX0|RX_CTX1| 259 */ 260 261 addr = lower_32_bits(prueth->msmcram.pa); 262 if (slice) 263 addr += PRUETH_NUM_BUF_POOLS * PRUETH_EMAC_BUF_POOL_SIZE; 264 265 if (addr % SZ_64K) { 266 dev_warn(prueth->dev, "buffer pool needs to be 64KB aligned\n"); 267 return -EINVAL; 268 } 269 270 bpool_cfg = emac->dram.va + BUFFER_POOL_0_ADDR_OFFSET; 271 /* workaround for f/w bug. bpool 0 needs to be initilalized */ 272 writel(addr, &bpool_cfg[0].addr); 273 writel(0, &bpool_cfg[0].len); 274 275 for (i = PRUETH_EMAC_BUF_POOL_START; 276 i < PRUETH_EMAC_BUF_POOL_START + PRUETH_NUM_BUF_POOLS; 277 i++) { 278 writel(addr, &bpool_cfg[i].addr); 279 writel(PRUETH_EMAC_BUF_POOL_SIZE, &bpool_cfg[i].len); 280 addr += PRUETH_EMAC_BUF_POOL_SIZE; 281 } 282 283 if (!slice) 284 addr += PRUETH_NUM_BUF_POOLS * PRUETH_EMAC_BUF_POOL_SIZE; 285 else 286 addr += PRUETH_EMAC_RX_CTX_BUF_SIZE * 2; 287 288 /* Pre-emptible RX buffer queue */ 289 rxq_ctx = emac->dram.va + HOST_RX_Q_PRE_CONTEXT_OFFSET; 290 for (i = 0; i < 3; i++) 291 writel(addr, &rxq_ctx->start[i]); 292 293 addr += PRUETH_EMAC_RX_CTX_BUF_SIZE; 294 writel(addr, &rxq_ctx->end); 295 296 /* Express RX buffer queue */ 297 rxq_ctx = emac->dram.va + HOST_RX_Q_EXP_CONTEXT_OFFSET; 298 for (i = 0; i < 3; i++) 299 writel(addr, &rxq_ctx->start[i]); 300 301 addr += PRUETH_EMAC_RX_CTX_BUF_SIZE; 302 writel(addr, &rxq_ctx->end); 303 304 return 0; 305 } 306 307 static void icssg_init_emac_mode(struct prueth *prueth) 308 { 309 /* When the device is configured as a bridge and it is being brought 310 * back to the emac mode, the host mac address has to be set as 0. 311 */ 312 u8 mac[ETH_ALEN] = { 0 }; 313 314 if (prueth->emacs_initialized) 315 return; 316 317 regmap_update_bits(prueth->miig_rt, FDB_GEN_CFG1, 318 SMEM_VLAN_OFFSET_MASK, 0); 319 regmap_write(prueth->miig_rt, FDB_GEN_CFG2, 0); 320 /* Clear host MAC address */ 321 icssg_class_set_host_mac_addr(prueth->miig_rt, mac); 322 } 323 324 int icssg_config(struct prueth *prueth, struct prueth_emac *emac, int slice) 325 { 326 void __iomem *config = emac->dram.va + ICSSG_CONFIG_OFFSET; 327 struct icssg_flow_cfg __iomem *flow_cfg; 328 int ret; 329 330 icssg_init_emac_mode(prueth); 331 332 memset_io(config, 0, TAS_GATE_MASK_LIST0); 333 icssg_miig_queues_init(prueth, slice); 334 335 emac->speed = SPEED_1000; 336 emac->duplex = DUPLEX_FULL; 337 if (!phy_interface_mode_is_rgmii(emac->phy_if)) { 338 emac->speed = SPEED_100; 339 emac->duplex = DUPLEX_FULL; 340 } 341 regmap_update_bits(prueth->miig_rt, ICSSG_CFG_OFFSET, 342 ICSSG_CFG_DEFAULT, ICSSG_CFG_DEFAULT); 343 icssg_miig_set_interface_mode(prueth->miig_rt, slice, emac->phy_if); 344 icssg_config_mii_init(emac); 345 icssg_config_ipg(emac); 346 icssg_update_rgmii_cfg(prueth->miig_rt, emac); 347 348 /* set GPI mode */ 349 pruss_cfg_gpimode(prueth->pruss, prueth->pru_id[slice], 350 PRUSS_GPI_MODE_MII); 351 352 /* enable XFR shift for PRU and RTU */ 353 pruss_cfg_xfr_enable(prueth->pruss, PRU_TYPE_PRU, true); 354 pruss_cfg_xfr_enable(prueth->pruss, PRU_TYPE_RTU, true); 355 356 /* set C28 to 0x100 */ 357 pru_rproc_set_ctable(prueth->pru[slice], PRU_C28, 0x100 << 8); 358 pru_rproc_set_ctable(prueth->rtu[slice], PRU_C28, 0x100 << 8); 359 pru_rproc_set_ctable(prueth->txpru[slice], PRU_C28, 0x100 << 8); 360 361 flow_cfg = config + PSI_L_REGULAR_FLOW_ID_BASE_OFFSET; 362 writew(emac->rx_flow_id_base, &flow_cfg->rx_base_flow); 363 writew(0, &flow_cfg->mgm_base_flow); 364 writeb(0, config + SPL_PKT_DEFAULT_PRIORITY); 365 writeb(0, config + QUEUE_NUM_UNTAGGED); 366 367 ret = prueth_emac_buffer_setup(emac); 368 if (ret) 369 return ret; 370 371 emac_r30_cmd_init(emac); 372 373 return 0; 374 } 375 376 /* Bitmask for ICSSG r30 commands */ 377 static const struct icssg_r30_cmd emac_r32_bitmask[] = { 378 {{0xffff0004, 0xffff0100, 0xffff0100, EMAC_NONE}}, /* EMAC_PORT_DISABLE */ 379 {{0xfffb0040, 0xfeff0200, 0xfeff0200, EMAC_NONE}}, /* EMAC_PORT_BLOCK */ 380 {{0xffbb0000, 0xfcff0000, 0xdcff0000, EMAC_NONE}}, /* EMAC_PORT_FORWARD */ 381 {{0xffbb0000, 0xfcff0000, 0xfcff2000, EMAC_NONE}}, /* EMAC_PORT_FORWARD_WO_LEARNING */ 382 {{0xffff0001, EMAC_NONE, EMAC_NONE, EMAC_NONE}}, /* ACCEPT ALL */ 383 {{0xfffe0002, EMAC_NONE, EMAC_NONE, EMAC_NONE}}, /* ACCEPT TAGGED */ 384 {{0xfffc0000, EMAC_NONE, EMAC_NONE, EMAC_NONE}}, /* ACCEPT UNTAGGED and PRIO */ 385 {{EMAC_NONE, 0xffff0020, EMAC_NONE, EMAC_NONE}}, /* TAS Trigger List change */ 386 {{EMAC_NONE, 0xdfff1000, EMAC_NONE, EMAC_NONE}}, /* TAS set state ENABLE*/ 387 {{EMAC_NONE, 0xefff2000, EMAC_NONE, EMAC_NONE}}, /* TAS set state RESET*/ 388 {{EMAC_NONE, 0xcfff0000, EMAC_NONE, EMAC_NONE}}, /* TAS set state DISABLE*/ 389 {{EMAC_NONE, EMAC_NONE, 0xffff0400, EMAC_NONE}}, /* UC flooding ENABLE*/ 390 {{EMAC_NONE, EMAC_NONE, 0xfbff0000, EMAC_NONE}}, /* UC flooding DISABLE*/ 391 {{EMAC_NONE, EMAC_NONE, 0xffff0800, EMAC_NONE}}, /* MC flooding ENABLE*/ 392 {{EMAC_NONE, EMAC_NONE, 0xf7ff0000, EMAC_NONE}}, /* MC flooding DISABLE*/ 393 {{EMAC_NONE, 0xffff4000, EMAC_NONE, EMAC_NONE}}, /* Preemption on Tx ENABLE*/ 394 {{EMAC_NONE, 0xbfff0000, EMAC_NONE, EMAC_NONE}}, /* Preemption on Tx DISABLE*/ 395 {{0xffff0010, EMAC_NONE, 0xffff0010, EMAC_NONE}}, /* VLAN AWARE*/ 396 {{0xffef0000, EMAC_NONE, 0xffef0000, EMAC_NONE}} /* VLAN UNWARE*/ 397 }; 398 399 int emac_set_port_state(struct prueth_emac *emac, 400 enum icssg_port_state_cmd cmd) 401 { 402 struct icssg_r30_cmd __iomem *p; 403 int ret = -ETIMEDOUT; 404 int done = 0; 405 int i; 406 407 p = emac->dram.va + MGR_R30_CMD_OFFSET; 408 409 if (cmd >= ICSSG_EMAC_PORT_MAX_COMMANDS) { 410 netdev_err(emac->ndev, "invalid port command\n"); 411 return -EINVAL; 412 } 413 414 /* only one command at a time allowed to firmware */ 415 mutex_lock(&emac->cmd_lock); 416 417 for (i = 0; i < 4; i++) 418 writel(emac_r32_bitmask[cmd].cmd[i], &p->cmd[i]); 419 420 /* wait for done */ 421 ret = read_poll_timeout(emac_r30_is_done, done, done == 1, 422 1000, 10000, false, emac); 423 424 if (ret == -ETIMEDOUT) 425 netdev_err(emac->ndev, "timeout waiting for command done\n"); 426 427 mutex_unlock(&emac->cmd_lock); 428 429 return ret; 430 } 431 432 void icssg_config_set_speed(struct prueth_emac *emac) 433 { 434 u8 fw_speed; 435 436 switch (emac->speed) { 437 case SPEED_1000: 438 fw_speed = FW_LINK_SPEED_1G; 439 break; 440 case SPEED_100: 441 fw_speed = FW_LINK_SPEED_100M; 442 break; 443 default: 444 /* Other links speeds not supported */ 445 netdev_err(emac->ndev, "Unsupported link speed\n"); 446 return; 447 } 448 449 writeb(fw_speed, emac->dram.va + PORT_LINK_SPEED_OFFSET); 450 } 451