Skip to content

Commit abd5576

Browse files
danish-tiPaolo Abeni
authored andcommitted
net: ti: icssg-prueth: Add support for ICSSG switch firmware
Add support for ICSSG switch firmware using existing Dual EMAC driver with switchdev. Limitations: VLAN offloading is limited to 0-256 IDs. MDB/FDB static entries are limited to 511 entries and different FDBs can hash to same bucket and thus may not completely offloaded Example assuming ETH1 and ETH2 as ICSSG2 interfaces: Switch to ICSSG Switch mode: ip link add name br0 type bridge ip link set dev eth1 master br0 ip link set dev eth2 master br0 ip link set dev br0 up bridge vlan add dev br0 vid 1 pvid untagged self Going back to Dual EMAC mode: ip link set dev br0 down ip link set dev eth1 nomaster ip link set dev eth2 nomaster ip link del name br0 type bridge By default, Dual EMAC firmware is loaded, and can be changed to switch mode by above steps Reviewed-by: Andrew Lunn <[email protected]> Signed-off-by: MD Danish Anwar <[email protected]> Signed-off-by: Paolo Abeni <[email protected]>
1 parent 972383a commit abd5576

File tree

7 files changed

+386
-19
lines changed

7 files changed

+386
-19
lines changed

drivers/net/ethernet/ti/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,7 @@ config TI_ICSSG_PRUETH_SR1
204204
select TI_ICSS_IEP
205205
select TI_K3_CPPI_DESC_POOL
206206
depends on PRU_REMOTEPROC
207+
depends on NET_SWITCHDEV
207208
depends on ARCH_K3 && OF && TI_K3_UDMA_GLUE_LAYER
208209
help
209210
Support dual Gigabit Ethernet ports over the ICSSG PRU Subsystem.

drivers/net/ethernet/ti/Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ icssg-prueth-y := icssg/icssg_prueth.o \
3939
icssg/icssg_config.o \
4040
icssg/icssg_mii_cfg.o \
4141
icssg/icssg_stats.o \
42-
icssg/icssg_ethtool.o
42+
icssg/icssg_ethtool.o \
43+
icssg/icssg_switchdev.o
4344
obj-$(CONFIG_TI_ICSSG_PRUETH_SR1) += icssg-prueth-sr1.o
4445
icssg-prueth-sr1-y := icssg/icssg_prueth_sr1.o \
4546
icssg/icssg_common.o \

drivers/net/ethernet/ti/icssg/icssg_classifier.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -455,7 +455,7 @@ void icssg_ft1_set_mac_addr(struct regmap *miig_rt, int slice, u8 *mac_addr)
455455
{
456456
const u8 mask_addr[] = { 0, 0, 0, 0, 0, 0, };
457457

458-
rx_class_ft1_set_start_len(miig_rt, slice, 0, 6);
458+
rx_class_ft1_set_start_len(miig_rt, slice, 6, 6);
459459
rx_class_ft1_set_da(miig_rt, slice, 0, mac_addr);
460460
rx_class_ft1_set_da_mask(miig_rt, slice, 0, mask_addr);
461461
rx_class_ft1_cfg_set_type(miig_rt, slice, 0, FT1_CFG_TYPE_EQ);

drivers/net/ethernet/ti/icssg/icssg_common.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -581,6 +581,8 @@ static int emac_rx_packet(struct prueth_emac *emac, u32 flow_id)
581581
} else {
582582
/* send the filled skb up the n/w stack */
583583
skb_put(skb, pkt_len);
584+
if (emac->prueth->is_switch_mode)
585+
skb->offload_fwd_mark = emac->offload_fwd_mark;
584586
skb->protocol = eth_type_trans(skb, ndev);
585587
napi_gro_receive(&emac->napi_rx, skb);
586588
ndev->stats.rx_bytes += pkt_len;

drivers/net/ethernet/ti/icssg/icssg_config.c

Lines changed: 138 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -107,28 +107,49 @@ static const struct map hwq_map[2][ICSSG_NUM_OTHER_QUEUES] = {
107107
},
108108
};
109109

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+
110137
static void icssg_config_mii_init(struct prueth_emac *emac)
111138
{
112-
u32 rxcfg, txcfg, rxcfg_reg, txcfg_reg, pcnt_reg;
113139
struct prueth *prueth = emac->prueth;
114140
int slice = prueth_emac_slice(emac);
141+
u32 txcfg, txcfg_reg, pcnt_reg;
115142
struct regmap *mii_rt;
116143

117144
mii_rt = prueth->mii_rt;
118145

119-
rxcfg_reg = (slice == ICSS_MII0) ? PRUSS_MII_RT_RXCFG0 :
120-
PRUSS_MII_RT_RXCFG1;
121146
txcfg_reg = (slice == ICSS_MII0) ? PRUSS_MII_RT_TXCFG0 :
122147
PRUSS_MII_RT_TXCFG1;
123148
pcnt_reg = (slice == ICSS_MII0) ? PRUSS_MII_RT_RX_PCNT0 :
124149
PRUSS_MII_RT_RX_PCNT1;
125150

126-
rxcfg = MII_RXCFG_DEFAULT;
127151
txcfg = MII_TXCFG_DEFAULT;
128152

129-
if (slice == ICSS_MII1)
130-
rxcfg |= PRUSS_MII_RT_RXCFG_RX_MUX_SEL;
131-
132153
/* In MII mode TX lines swapped inside ICSSG, so TX_MUX_SEL cfg need
133154
* to be swapped also comparing to RGMII mode.
134155
*/
@@ -137,7 +158,6 @@ static void icssg_config_mii_init(struct prueth_emac *emac)
137158
else if (emac->phy_if != PHY_INTERFACE_MODE_MII && slice == ICSS_MII1)
138159
txcfg |= PRUSS_MII_RT_TXCFG_TX_MUX_SEL;
139160

140-
regmap_write(mii_rt, rxcfg_reg, rxcfg);
141161
regmap_write(mii_rt, txcfg_reg, txcfg);
142162
regmap_write(mii_rt, pcnt_reg, 0x1);
143163
}
@@ -257,6 +277,66 @@ static int emac_r30_is_done(struct prueth_emac *emac)
257277
return 1;
258278
}
259279

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+
260340
static int prueth_emac_buffer_setup(struct prueth_emac *emac)
261341
{
262342
struct icssg_buffer_pool_cfg __iomem *bpool_cfg;
@@ -321,25 +401,63 @@ static void icssg_init_emac_mode(struct prueth *prueth)
321401
/* When the device is configured as a bridge and it is being brought
322402
* back to the emac mode, the host mac address has to be set as 0.
323403
*/
404+
u32 addr = prueth->shram.pa + EMAC_ICSSG_SWITCH_DEFAULT_VLAN_TABLE_OFFSET;
405+
int i;
324406
u8 mac[ETH_ALEN] = { 0 };
325407

326408
if (prueth->emacs_initialized)
327409
return;
328410

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);
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+
}
332422
/* Clear host MAC address */
333423
icssg_class_set_host_mac_addr(prueth->miig_rt, mac);
334424
}
335425

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+
336451
int icssg_config(struct prueth *prueth, struct prueth_emac *emac, int slice)
337452
{
338453
void __iomem *config = emac->dram.va + ICSSG_CONFIG_OFFSET;
339454
struct icssg_flow_cfg __iomem *flow_cfg;
340455
int ret;
341456

342-
icssg_init_emac_mode(prueth);
457+
if (prueth->is_switch_mode)
458+
icssg_init_switch_mode(prueth);
459+
else
460+
icssg_init_emac_mode(prueth);
343461

344462
memset_io(config, 0, TAS_GATE_MASK_LIST0);
345463
icssg_miig_queues_init(prueth, slice);
@@ -353,7 +471,10 @@ int icssg_config(struct prueth *prueth, struct prueth_emac *emac, int slice)
353471
regmap_update_bits(prueth->miig_rt, ICSSG_CFG_OFFSET,
354472
ICSSG_CFG_DEFAULT, ICSSG_CFG_DEFAULT);
355473
icssg_miig_set_interface_mode(prueth->miig_rt, slice, emac->phy_if);
356-
icssg_config_mii_init(emac);
474+
if (prueth->is_switch_mode)
475+
icssg_config_mii_init_switch(emac);
476+
else
477+
icssg_config_mii_init(emac);
357478
icssg_config_ipg(emac);
358479
icssg_update_rgmii_cfg(prueth->miig_rt, emac);
359480

@@ -376,7 +497,10 @@ int icssg_config(struct prueth *prueth, struct prueth_emac *emac, int slice)
376497
writeb(0, config + SPL_PKT_DEFAULT_PRIORITY);
377498
writeb(0, config + QUEUE_NUM_UNTAGGED);
378499

379-
ret = prueth_emac_buffer_setup(emac);
500+
if (prueth->is_switch_mode)
501+
ret = prueth_switch_buffer_setup(emac);
502+
else
503+
ret = prueth_emac_buffer_setup(emac);
380504
if (ret)
381505
return ret;
382506

drivers/net/ethernet/ti/icssg/icssg_config.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,13 @@ struct icssg_flow_cfg {
3535
(2 * (PRUETH_EMAC_BUF_POOL_SIZE * PRUETH_NUM_BUF_POOLS + \
3636
PRUETH_EMAC_RX_CTX_BUF_SIZE * 2))
3737

38+
#define PRUETH_SW_BUF_POOL_SIZE_HOST SZ_4K
39+
#define PRUETH_SW_NUM_BUF_POOLS_HOST 8
40+
#define PRUETH_SW_NUM_BUF_POOLS_PER_PRU 4
41+
#define MSMC_RAM_SIZE_SWITCH_MODE \
42+
(MSMC_RAM_SIZE + \
43+
(2 * PRUETH_SW_BUF_POOL_SIZE_HOST * PRUETH_SW_NUM_BUF_POOLS_HOST))
44+
3845
#define PRUETH_SWITCH_FDB_MASK ((SIZE_OF_FDB / NUMBER_OF_FDB_BUCKET_ENTRIES) - 1)
3946

4047
struct icssg_rxq_ctx {

0 commit comments

Comments
 (0)