bcm63xx_enet: add support for Broadcom BCM63xx integrated gigabit switch

Newer Broadcom BCM63xx SoCs: 6328, 6362 and 6368 have an integrated switch
which needs to be driven slightly differently from the traditional
external switches. This patch introduces changes in arch/mips/bcm63xx in order
to:

- register a bcm63xx_enetsw driver instead of bcm63xx_enet driver
- update DMA channels configuration & state RAM base addresses
- add a new platform data configuration knob to define the number of
  ports per switch/device and force link on some ports
- define the required switch registers

On the driver side, the following changes are required:

- the switch ports need to be polled to ensure the link is up and
  running and RX/TX can properly work
- basic switch configuration needs to be performed for the switch to
  forward packets to the CPU
- update the MIB counters since the integrated

Signed-off-by: Maxime Bizon <mbizon@freebox.fr>
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Maxime Bizon
2013-06-04 22:53:35 +01:00
committed by David S. Miller
parent 0ae99b5fed
commit 6f00a02296
7 changed files with 1177 additions and 30 deletions

View File

@@ -104,6 +104,64 @@ static struct platform_device bcm63xx_enet1_device = {
},
};
static struct resource enetsw_res[] = {
{
/* start & end filled at runtime */
.flags = IORESOURCE_MEM,
},
{
/* start filled at runtime */
.flags = IORESOURCE_IRQ,
},
{
/* start filled at runtime */
.flags = IORESOURCE_IRQ,
},
};
static struct bcm63xx_enetsw_platform_data enetsw_pd;
static struct platform_device bcm63xx_enetsw_device = {
.name = "bcm63xx_enetsw",
.num_resources = ARRAY_SIZE(enetsw_res),
.resource = enetsw_res,
.dev = {
.platform_data = &enetsw_pd,
},
};
static int __init register_shared(void)
{
int ret, chan_count;
if (shared_device_registered)
return 0;
shared_res[0].start = bcm63xx_regset_address(RSET_ENETDMA);
shared_res[0].end = shared_res[0].start;
shared_res[0].end += (RSET_ENETDMA_SIZE) - 1;
if (BCMCPU_IS_6328() || BCMCPU_IS_6362() || BCMCPU_IS_6368())
chan_count = 32;
else
chan_count = 16;
shared_res[1].start = bcm63xx_regset_address(RSET_ENETDMAC);
shared_res[1].end = shared_res[1].start;
shared_res[1].end += RSET_ENETDMAC_SIZE(chan_count) - 1;
shared_res[2].start = bcm63xx_regset_address(RSET_ENETDMAS);
shared_res[2].end = shared_res[2].start;
shared_res[2].end += RSET_ENETDMAS_SIZE(chan_count) - 1;
ret = platform_device_register(&bcm63xx_enet_shared_device);
if (ret)
return ret;
shared_device_registered = 1;
return 0;
}
int __init bcm63xx_enet_register(int unit,
const struct bcm63xx_enet_platform_data *pd)
{
@@ -117,24 +175,9 @@ int __init bcm63xx_enet_register(int unit,
if (unit == 1 && BCMCPU_IS_6338())
return -ENODEV;
if (!shared_device_registered) {
shared_res[0].start = bcm63xx_regset_address(RSET_ENETDMA);
shared_res[0].end = shared_res[0].start;
shared_res[0].end += (RSET_ENETDMA_SIZE) - 1;
shared_res[1].start = bcm63xx_regset_address(RSET_ENETDMAC);
shared_res[1].end = shared_res[1].start;
shared_res[1].end += RSET_ENETDMAC_SIZE(16) - 1;
shared_res[2].start = bcm63xx_regset_address(RSET_ENETDMAS);
shared_res[2].end = shared_res[2].start;
shared_res[2].end += RSET_ENETDMAS_SIZE(16) - 1;
ret = platform_device_register(&bcm63xx_enet_shared_device);
if (ret)
return ret;
shared_device_registered = 1;
}
ret = register_shared();
if (ret)
return ret;
if (unit == 0) {
enet0_res[0].start = bcm63xx_regset_address(RSET_ENET0);
@@ -175,3 +218,37 @@ int __init bcm63xx_enet_register(int unit,
return ret;
return 0;
}
int __init
bcm63xx_enetsw_register(const struct bcm63xx_enetsw_platform_data *pd)
{
int ret;
if (!BCMCPU_IS_6328() && !BCMCPU_IS_6362() && !BCMCPU_IS_6368())
return -ENODEV;
ret = register_shared();
if (ret)
return ret;
enetsw_res[0].start = bcm63xx_regset_address(RSET_ENETSW);
enetsw_res[0].end = enetsw_res[0].start;
enetsw_res[0].end += RSET_ENETSW_SIZE - 1;
enetsw_res[1].start = bcm63xx_get_irq_number(IRQ_ENETSW_RXDMA0);
enetsw_res[2].start = bcm63xx_get_irq_number(IRQ_ENETSW_TXDMA0);
if (!enetsw_res[2].start)
enetsw_res[2].start = -1;
memcpy(bcm63xx_enetsw_device.dev.platform_data, pd, sizeof(*pd));
if (BCMCPU_IS_6328())
enetsw_pd.num_ports = ENETSW_PORTS_6328;
else if (BCMCPU_IS_6362() || BCMCPU_IS_6368())
enetsw_pd.num_ports = ENETSW_PORTS_6368;
ret = platform_device_register(&bcm63xx_enetsw_device);
if (ret)
return ret;
return 0;
}