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:
parent
0ae99b5fed
commit
6f00a02296
|
@ -845,6 +845,10 @@ int __init board_register_devices(void)
|
|||
!bcm63xx_nvram_get_mac_address(board.enet1.mac_addr))
|
||||
bcm63xx_enet_register(1, &board.enet1);
|
||||
|
||||
if (board.has_enetsw &&
|
||||
!bcm63xx_nvram_get_mac_address(board.enetsw.mac_addr))
|
||||
bcm63xx_enetsw_register(&board.enetsw);
|
||||
|
||||
if (board.has_usbd)
|
||||
bcm63xx_usbd_register(&board.usbd);
|
||||
|
||||
|
|
|
@ -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);
|
||||
ret = register_shared();
|
||||
if (ret)
|
||||
return ret;
|
||||
shared_device_registered = 1;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -39,7 +39,35 @@ struct bcm63xx_enet_platform_data {
|
|||
int phy_id, int reg, int val));
|
||||
};
|
||||
|
||||
/*
|
||||
* on board ethernet switch platform data
|
||||
*/
|
||||
#define ENETSW_MAX_PORT 8
|
||||
#define ENETSW_PORTS_6328 5 /* 4 FE PHY + 1 RGMII */
|
||||
#define ENETSW_PORTS_6368 6 /* 4 FE PHY + 2 RGMII */
|
||||
|
||||
#define ENETSW_RGMII_PORT0 4
|
||||
|
||||
struct bcm63xx_enetsw_port {
|
||||
int used;
|
||||
int phy_id;
|
||||
|
||||
int bypass_link;
|
||||
int force_speed;
|
||||
int force_duplex_full;
|
||||
|
||||
const char *name;
|
||||
};
|
||||
|
||||
struct bcm63xx_enetsw_platform_data {
|
||||
char mac_addr[ETH_ALEN];
|
||||
int num_ports;
|
||||
struct bcm63xx_enetsw_port used_ports[ENETSW_MAX_PORT];
|
||||
};
|
||||
|
||||
int __init bcm63xx_enet_register(int unit,
|
||||
const struct bcm63xx_enet_platform_data *pd);
|
||||
|
||||
int bcm63xx_enetsw_register(const struct bcm63xx_enetsw_platform_data *pd);
|
||||
|
||||
#endif /* ! BCM63XX_DEV_ENET_H_ */
|
||||
|
|
|
@ -830,10 +830,60 @@
|
|||
* _REG relative to RSET_ENETSW
|
||||
*************************************************************************/
|
||||
|
||||
/* Port traffic control */
|
||||
#define ENETSW_PTCTRL_REG(x) (0x0 + (x))
|
||||
#define ENETSW_PTCTRL_RXDIS_MASK (1 << 0)
|
||||
#define ENETSW_PTCTRL_TXDIS_MASK (1 << 1)
|
||||
|
||||
/* Switch mode register */
|
||||
#define ENETSW_SWMODE_REG (0xb)
|
||||
#define ENETSW_SWMODE_FWD_EN_MASK (1 << 1)
|
||||
|
||||
/* IMP override Register */
|
||||
#define ENETSW_IMPOV_REG (0xe)
|
||||
#define ENETSW_IMPOV_FORCE_MASK (1 << 7)
|
||||
#define ENETSW_IMPOV_TXFLOW_MASK (1 << 5)
|
||||
#define ENETSW_IMPOV_RXFLOW_MASK (1 << 4)
|
||||
#define ENETSW_IMPOV_1000_MASK (1 << 3)
|
||||
#define ENETSW_IMPOV_100_MASK (1 << 2)
|
||||
#define ENETSW_IMPOV_FDX_MASK (1 << 1)
|
||||
#define ENETSW_IMPOV_LINKUP_MASK (1 << 0)
|
||||
|
||||
/* Port override Register */
|
||||
#define ENETSW_PORTOV_REG(x) (0x58 + (x))
|
||||
#define ENETSW_PORTOV_ENABLE_MASK (1 << 6)
|
||||
#define ENETSW_PORTOV_TXFLOW_MASK (1 << 5)
|
||||
#define ENETSW_PORTOV_RXFLOW_MASK (1 << 4)
|
||||
#define ENETSW_PORTOV_1000_MASK (1 << 3)
|
||||
#define ENETSW_PORTOV_100_MASK (1 << 2)
|
||||
#define ENETSW_PORTOV_FDX_MASK (1 << 1)
|
||||
#define ENETSW_PORTOV_LINKUP_MASK (1 << 0)
|
||||
|
||||
/* MDIO control register */
|
||||
#define ENETSW_MDIOC_REG (0xb0)
|
||||
#define ENETSW_MDIOC_EXT_MASK (1 << 16)
|
||||
#define ENETSW_MDIOC_REG_SHIFT 20
|
||||
#define ENETSW_MDIOC_PHYID_SHIFT 25
|
||||
#define ENETSW_MDIOC_RD_MASK (1 << 30)
|
||||
#define ENETSW_MDIOC_WR_MASK (1 << 31)
|
||||
|
||||
/* MDIO data register */
|
||||
#define ENETSW_MDIOD_REG (0xb4)
|
||||
|
||||
/* Global Management Configuration Register */
|
||||
#define ENETSW_GMCR_REG (0x200)
|
||||
#define ENETSW_GMCR_RST_MIB_MASK (1 << 0)
|
||||
|
||||
/* MIB register */
|
||||
#define ENETSW_MIB_REG(x) (0x2800 + (x) * 4)
|
||||
#define ENETSW_MIB_REG_COUNT 47
|
||||
|
||||
/* Jumbo control register port mask register */
|
||||
#define ENETSW_JMBCTL_PORT_REG (0x4004)
|
||||
|
||||
/* Jumbo control mib good frame register */
|
||||
#define ENETSW_JMBCTL_MAXSIZE_REG (0x4008)
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* _REG relative to RSET_OHCI_PRIV
|
||||
|
|
|
@ -24,6 +24,7 @@ struct board_info {
|
|||
/* enabled feature/device */
|
||||
unsigned int has_enet0:1;
|
||||
unsigned int has_enet1:1;
|
||||
unsigned int has_enetsw:1;
|
||||
unsigned int has_pci:1;
|
||||
unsigned int has_pccard:1;
|
||||
unsigned int has_ohci0:1;
|
||||
|
@ -36,6 +37,7 @@ struct board_info {
|
|||
/* ethernet config */
|
||||
struct bcm63xx_enet_platform_data enet0;
|
||||
struct bcm63xx_enet_platform_data enet1;
|
||||
struct bcm63xx_enetsw_platform_data enetsw;
|
||||
|
||||
/* USB config */
|
||||
struct bcm63xx_usbd_platform_data usbd;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -18,6 +18,7 @@
|
|||
|
||||
/* maximum burst len for dma (4 bytes unit) */
|
||||
#define BCMENET_DMA_MAXBURST 16
|
||||
#define BCMENETSW_DMA_MAXBURST 8
|
||||
|
||||
/* tx transmit threshold (4 bytes unit), fifo is 256 bytes, the value
|
||||
* must be low enough so that a DMA transfer of above burst length can
|
||||
|
@ -84,11 +85,60 @@
|
|||
#define ETH_MIB_RX_CNTRL 54
|
||||
|
||||
|
||||
/*
|
||||
* SW MIB Counters register definitions
|
||||
*/
|
||||
#define ETHSW_MIB_TX_ALL_OCT 0
|
||||
#define ETHSW_MIB_TX_DROP_PKTS 2
|
||||
#define ETHSW_MIB_TX_QOS_PKTS 3
|
||||
#define ETHSW_MIB_TX_BRDCAST 4
|
||||
#define ETHSW_MIB_TX_MULT 5
|
||||
#define ETHSW_MIB_TX_UNI 6
|
||||
#define ETHSW_MIB_TX_COL 7
|
||||
#define ETHSW_MIB_TX_1_COL 8
|
||||
#define ETHSW_MIB_TX_M_COL 9
|
||||
#define ETHSW_MIB_TX_DEF 10
|
||||
#define ETHSW_MIB_TX_LATE 11
|
||||
#define ETHSW_MIB_TX_EX_COL 12
|
||||
#define ETHSW_MIB_TX_PAUSE 14
|
||||
#define ETHSW_MIB_TX_QOS_OCT 15
|
||||
|
||||
#define ETHSW_MIB_RX_ALL_OCT 17
|
||||
#define ETHSW_MIB_RX_UND 19
|
||||
#define ETHSW_MIB_RX_PAUSE 20
|
||||
#define ETHSW_MIB_RX_64 21
|
||||
#define ETHSW_MIB_RX_65_127 22
|
||||
#define ETHSW_MIB_RX_128_255 23
|
||||
#define ETHSW_MIB_RX_256_511 24
|
||||
#define ETHSW_MIB_RX_512_1023 25
|
||||
#define ETHSW_MIB_RX_1024_1522 26
|
||||
#define ETHSW_MIB_RX_OVR 27
|
||||
#define ETHSW_MIB_RX_JAB 28
|
||||
#define ETHSW_MIB_RX_ALIGN 29
|
||||
#define ETHSW_MIB_RX_CRC 30
|
||||
#define ETHSW_MIB_RX_GD_OCT 31
|
||||
#define ETHSW_MIB_RX_DROP 33
|
||||
#define ETHSW_MIB_RX_UNI 34
|
||||
#define ETHSW_MIB_RX_MULT 35
|
||||
#define ETHSW_MIB_RX_BRDCAST 36
|
||||
#define ETHSW_MIB_RX_SA_CHANGE 37
|
||||
#define ETHSW_MIB_RX_FRAG 38
|
||||
#define ETHSW_MIB_RX_OVR_DISC 39
|
||||
#define ETHSW_MIB_RX_SYM 40
|
||||
#define ETHSW_MIB_RX_QOS_PKTS 41
|
||||
#define ETHSW_MIB_RX_QOS_OCT 42
|
||||
#define ETHSW_MIB_RX_1523_2047 44
|
||||
#define ETHSW_MIB_RX_2048_4095 45
|
||||
#define ETHSW_MIB_RX_4096_8191 46
|
||||
#define ETHSW_MIB_RX_8192_9728 47
|
||||
|
||||
|
||||
struct bcm_enet_mib_counters {
|
||||
u64 tx_gd_octets;
|
||||
u32 tx_gd_pkts;
|
||||
u32 tx_all_octets;
|
||||
u32 tx_all_pkts;
|
||||
u32 tx_unicast;
|
||||
u32 tx_brdcast;
|
||||
u32 tx_mult;
|
||||
u32 tx_64;
|
||||
|
@ -97,7 +147,12 @@ struct bcm_enet_mib_counters {
|
|||
u32 tx_256_511;
|
||||
u32 tx_512_1023;
|
||||
u32 tx_1024_max;
|
||||
u32 tx_1523_2047;
|
||||
u32 tx_2048_4095;
|
||||
u32 tx_4096_8191;
|
||||
u32 tx_8192_9728;
|
||||
u32 tx_jab;
|
||||
u32 tx_drop;
|
||||
u32 tx_ovr;
|
||||
u32 tx_frag;
|
||||
u32 tx_underrun;
|
||||
|
@ -114,6 +169,7 @@ struct bcm_enet_mib_counters {
|
|||
u32 rx_all_octets;
|
||||
u32 rx_all_pkts;
|
||||
u32 rx_brdcast;
|
||||
u32 rx_unicast;
|
||||
u32 rx_mult;
|
||||
u32 rx_64;
|
||||
u32 rx_65_127;
|
||||
|
@ -197,6 +253,9 @@ struct bcm_enet_priv {
|
|||
/* number of dma desc in tx ring */
|
||||
int tx_ring_size;
|
||||
|
||||
/* maximum dma burst size */
|
||||
int dma_maxburst;
|
||||
|
||||
/* cpu view of rx dma ring */
|
||||
struct bcm_enet_desc *tx_desc_cpu;
|
||||
|
||||
|
@ -269,6 +328,18 @@ struct bcm_enet_priv {
|
|||
|
||||
/* maximum hardware transmit/receive size */
|
||||
unsigned int hw_mtu;
|
||||
|
||||
bool enet_is_sw;
|
||||
|
||||
/* port mapping for switch devices */
|
||||
int num_ports;
|
||||
struct bcm63xx_enetsw_port used_ports[ENETSW_MAX_PORT];
|
||||
int sw_port_link[ENETSW_MAX_PORT];
|
||||
|
||||
/* used to poll switch port state */
|
||||
struct timer_list swphy_poll;
|
||||
spinlock_t enetsw_mdio_lock;
|
||||
};
|
||||
|
||||
|
||||
#endif /* ! BCM63XX_ENET_H_ */
|
||||
|
|
Loading…
Reference in New Issue