@@ -107,28 +107,49 @@ static const struct map hwq_map[2][ICSSG_NUM_OTHER_QUEUES] = {
107
107
},
108
108
};
109
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
+
110
137
static void icssg_config_mii_init (struct prueth_emac * emac )
111
138
{
112
- u32 rxcfg , txcfg , rxcfg_reg , txcfg_reg , pcnt_reg ;
113
139
struct prueth * prueth = emac -> prueth ;
114
140
int slice = prueth_emac_slice (emac );
141
+ u32 txcfg , txcfg_reg , pcnt_reg ;
115
142
struct regmap * mii_rt ;
116
143
117
144
mii_rt = prueth -> mii_rt ;
118
145
119
- rxcfg_reg = (slice == ICSS_MII0 ) ? PRUSS_MII_RT_RXCFG0 :
120
- PRUSS_MII_RT_RXCFG1 ;
121
146
txcfg_reg = (slice == ICSS_MII0 ) ? PRUSS_MII_RT_TXCFG0 :
122
147
PRUSS_MII_RT_TXCFG1 ;
123
148
pcnt_reg = (slice == ICSS_MII0 ) ? PRUSS_MII_RT_RX_PCNT0 :
124
149
PRUSS_MII_RT_RX_PCNT1 ;
125
150
126
- rxcfg = MII_RXCFG_DEFAULT ;
127
151
txcfg = MII_TXCFG_DEFAULT ;
128
152
129
- if (slice == ICSS_MII1 )
130
- rxcfg |= PRUSS_MII_RT_RXCFG_RX_MUX_SEL ;
131
-
132
153
/* In MII mode TX lines swapped inside ICSSG, so TX_MUX_SEL cfg need
133
154
* to be swapped also comparing to RGMII mode.
134
155
*/
@@ -137,7 +158,6 @@ static void icssg_config_mii_init(struct prueth_emac *emac)
137
158
else if (emac -> phy_if != PHY_INTERFACE_MODE_MII && slice == ICSS_MII1 )
138
159
txcfg |= PRUSS_MII_RT_TXCFG_TX_MUX_SEL ;
139
160
140
- regmap_write (mii_rt , rxcfg_reg , rxcfg );
141
161
regmap_write (mii_rt , txcfg_reg , txcfg );
142
162
regmap_write (mii_rt , pcnt_reg , 0x1 );
143
163
}
@@ -257,6 +277,66 @@ static int emac_r30_is_done(struct prueth_emac *emac)
257
277
return 1 ;
258
278
}
259
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
+
260
340
static int prueth_emac_buffer_setup (struct prueth_emac * emac )
261
341
{
262
342
struct icssg_buffer_pool_cfg __iomem * bpool_cfg ;
@@ -321,25 +401,63 @@ static void icssg_init_emac_mode(struct prueth *prueth)
321
401
/* When the device is configured as a bridge and it is being brought
322
402
* back to the emac mode, the host mac address has to be set as 0.
323
403
*/
404
+ u32 addr = prueth -> shram .pa + EMAC_ICSSG_SWITCH_DEFAULT_VLAN_TABLE_OFFSET ;
405
+ int i ;
324
406
u8 mac [ETH_ALEN ] = { 0 };
325
407
326
408
if (prueth -> emacs_initialized )
327
409
return ;
328
410
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
+ }
332
422
/* Clear host MAC address */
333
423
icssg_class_set_host_mac_addr (prueth -> miig_rt , mac );
334
424
}
335
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
+
336
451
int icssg_config (struct prueth * prueth , struct prueth_emac * emac , int slice )
337
452
{
338
453
void __iomem * config = emac -> dram .va + ICSSG_CONFIG_OFFSET ;
339
454
struct icssg_flow_cfg __iomem * flow_cfg ;
340
455
int ret ;
341
456
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 );
343
461
344
462
memset_io (config , 0 , TAS_GATE_MASK_LIST0 );
345
463
icssg_miig_queues_init (prueth , slice );
@@ -353,7 +471,10 @@ int icssg_config(struct prueth *prueth, struct prueth_emac *emac, int slice)
353
471
regmap_update_bits (prueth -> miig_rt , ICSSG_CFG_OFFSET ,
354
472
ICSSG_CFG_DEFAULT , ICSSG_CFG_DEFAULT );
355
473
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 );
357
478
icssg_config_ipg (emac );
358
479
icssg_update_rgmii_cfg (prueth -> miig_rt , emac );
359
480
@@ -376,7 +497,10 @@ int icssg_config(struct prueth *prueth, struct prueth_emac *emac, int slice)
376
497
writeb (0 , config + SPL_PKT_DEFAULT_PRIORITY );
377
498
writeb (0 , config + QUEUE_NUM_UNTAGGED );
378
499
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 );
380
504
if (ret )
381
505
return ret ;
382
506
0 commit comments