@@ -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+
110137static 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+
260340static 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+
336451int 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
0 commit comments