mirror of
https://github.com/torvalds/linux.git
synced 2024-11-20 11:01:38 +00:00
macb: initial support for Cadence GEM
The Cadence GEM is based on the MACB Ethernet controller but has a few small changes with regards to register and bitfield placement. This patch detects the presence of a GEM by reading the module ID register and setting a flag appropriately. This handles the new HW address, USRIO and hash register base register locations in GEM. v3: - convert to macb_is_gem() inline rather than storing a boolean flag - handle rx_overrun stats for gem Acked-by: David S. Miller <davem@davemloft.net> Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com> Cc: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> Signed-off-by: Jamie Iles <jamie@jamieiles.com> Tested-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
This commit is contained in:
parent
c220f8cd01
commit
f75ba50bdc
@ -10,7 +10,7 @@ obj-$(CONFIG_NET_VENDOR_ALTEON) += alteon/
|
||||
obj-$(CONFIG_NET_VENDOR_AMD) += amd/
|
||||
obj-$(CONFIG_NET_VENDOR_APPLE) += apple/
|
||||
obj-$(CONFIG_NET_VENDOR_ATHEROS) += atheros/
|
||||
obj-$(CONFIG_NET_ATMEL) += cadence/
|
||||
obj-$(CONFIG_NET_CADENCE) += cadence/
|
||||
obj-$(CONFIG_NET_BFIN) += adi/
|
||||
obj-$(CONFIG_NET_VENDOR_BROADCOM) += broadcom/
|
||||
obj-$(CONFIG_NET_VENDOR_BROCADE) += brocade/
|
||||
|
@ -5,8 +5,8 @@
|
||||
config HAVE_NET_MACB
|
||||
bool
|
||||
|
||||
config NET_ATMEL
|
||||
bool "Atmel devices"
|
||||
config NET_CADENCE
|
||||
bool "Cadence devices"
|
||||
depends on HAVE_NET_MACB || (ARM && ARCH_AT91RM9200)
|
||||
---help---
|
||||
If you have a network (Ethernet) card belonging to this class, say Y.
|
||||
@ -20,7 +20,7 @@ config NET_ATMEL
|
||||
the remaining Atmel network card questions. If you say Y, you will be
|
||||
asked for your specific card in the following questions.
|
||||
|
||||
if NET_ATMEL
|
||||
if NET_CADENCE
|
||||
|
||||
config ARM_AT91_ETHER
|
||||
tristate "AT91RM9200 Ethernet support"
|
||||
@ -32,14 +32,16 @@ config ARM_AT91_ETHER
|
||||
ethernet support, then you should always answer Y to this.
|
||||
|
||||
config MACB
|
||||
tristate "Atmel MACB support"
|
||||
tristate "Cadence MACB/GEM support"
|
||||
depends on HAVE_NET_MACB
|
||||
select PHYLIB
|
||||
---help---
|
||||
The Atmel MACB ethernet interface is found on many AT32 and AT91
|
||||
parts. Say Y to include support for the MACB chip.
|
||||
The Cadence MACB ethernet interface is found on many Atmel AT32 and
|
||||
AT91 parts. This driver also supports the Cadence GEM (Gigabit
|
||||
Ethernet MAC found in some ARM SoC devices). Note: the Gigabit mode
|
||||
is not yet supported. Say Y to include support for the MACB/GEM chip.
|
||||
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called macb.
|
||||
|
||||
endif # NET_ATMEL
|
||||
endif # NET_CADENCE
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Atmel MACB Ethernet Controller driver
|
||||
* Cadence MACB/GEM Ethernet Controller driver
|
||||
*
|
||||
* Copyright (C) 2004-2006 Atmel Corporation
|
||||
*
|
||||
@ -59,9 +59,9 @@ static void __macb_set_hwaddr(struct macb *bp)
|
||||
u16 top;
|
||||
|
||||
bottom = cpu_to_le32(*((u32 *)bp->dev->dev_addr));
|
||||
macb_writel(bp, SA1B, bottom);
|
||||
macb_or_gem_writel(bp, SA1B, bottom);
|
||||
top = cpu_to_le16(*((u16 *)(bp->dev->dev_addr + 4)));
|
||||
macb_writel(bp, SA1T, top);
|
||||
macb_or_gem_writel(bp, SA1T, top);
|
||||
}
|
||||
|
||||
static void __init macb_get_hwaddr(struct macb *bp)
|
||||
@ -70,8 +70,8 @@ static void __init macb_get_hwaddr(struct macb *bp)
|
||||
u16 top;
|
||||
u8 addr[6];
|
||||
|
||||
bottom = macb_readl(bp, SA1B);
|
||||
top = macb_readl(bp, SA1T);
|
||||
bottom = macb_or_gem_readl(bp, SA1B);
|
||||
top = macb_or_gem_readl(bp, SA1T);
|
||||
|
||||
addr[0] = bottom & 0xff;
|
||||
addr[1] = (bottom >> 8) & 0xff;
|
||||
@ -580,7 +580,10 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id)
|
||||
|
||||
if (status & MACB_BIT(ISR_ROVR)) {
|
||||
/* We missed at least one packet */
|
||||
bp->hw_stats.rx_overruns++;
|
||||
if (macb_is_gem(bp))
|
||||
bp->hw_stats.gem.rx_overruns++;
|
||||
else
|
||||
bp->hw_stats.macb.rx_overruns++;
|
||||
}
|
||||
|
||||
if (status & MACB_BIT(HRESP)) {
|
||||
@ -902,8 +905,8 @@ static void macb_sethashtable(struct net_device *dev)
|
||||
mc_filter[bitnr >> 5] |= 1 << (bitnr & 31);
|
||||
}
|
||||
|
||||
macb_writel(bp, HRB, mc_filter[0]);
|
||||
macb_writel(bp, HRT, mc_filter[1]);
|
||||
macb_or_gem_writel(bp, HRB, mc_filter[0]);
|
||||
macb_or_gem_writel(bp, HRT, mc_filter[1]);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -925,8 +928,8 @@ static void macb_set_rx_mode(struct net_device *dev)
|
||||
|
||||
if (dev->flags & IFF_ALLMULTI) {
|
||||
/* Enable all multicast mode */
|
||||
macb_writel(bp, HRB, -1);
|
||||
macb_writel(bp, HRT, -1);
|
||||
macb_or_gem_writel(bp, HRB, -1);
|
||||
macb_or_gem_writel(bp, HRT, -1);
|
||||
cfg |= MACB_BIT(NCFGR_MTI);
|
||||
} else if (!netdev_mc_empty(dev)) {
|
||||
/* Enable specific multicasts */
|
||||
@ -934,8 +937,8 @@ static void macb_set_rx_mode(struct net_device *dev)
|
||||
cfg |= MACB_BIT(NCFGR_MTI);
|
||||
} else if (dev->flags & (~IFF_ALLMULTI)) {
|
||||
/* Disable all multicast mode */
|
||||
macb_writel(bp, HRB, 0);
|
||||
macb_writel(bp, HRT, 0);
|
||||
macb_or_gem_writel(bp, HRB, 0);
|
||||
macb_or_gem_writel(bp, HRT, 0);
|
||||
cfg &= ~MACB_BIT(NCFGR_MTI);
|
||||
}
|
||||
|
||||
@ -1196,15 +1199,16 @@ static int __init macb_probe(struct platform_device *pdev)
|
||||
|
||||
if (pdata && pdata->is_rmii)
|
||||
#if defined(CONFIG_ARCH_AT91)
|
||||
macb_writel(bp, USRIO, (MACB_BIT(RMII) | MACB_BIT(CLKEN)) );
|
||||
macb_or_gem_writel(bp, USRIO, (MACB_BIT(RMII) |
|
||||
MACB_BIT(CLKEN)));
|
||||
#else
|
||||
macb_writel(bp, USRIO, 0);
|
||||
macb_or_gem_writel(bp, USRIO, 0);
|
||||
#endif
|
||||
else
|
||||
#if defined(CONFIG_ARCH_AT91)
|
||||
macb_writel(bp, USRIO, MACB_BIT(CLKEN));
|
||||
macb_or_gem_writel(bp, USRIO, MACB_BIT(CLKEN));
|
||||
#else
|
||||
macb_writel(bp, USRIO, MACB_BIT(MII));
|
||||
macb_or_gem_writel(bp, USRIO, MACB_BIT(MII));
|
||||
#endif
|
||||
|
||||
bp->tx_pending = DEF_TX_RING_PENDING;
|
||||
@ -1221,8 +1225,9 @@ static int __init macb_probe(struct platform_device *pdev)
|
||||
|
||||
platform_set_drvdata(pdev, dev);
|
||||
|
||||
netdev_info(dev, "Atmel MACB at 0x%08lx irq %d (%pM)\n",
|
||||
dev->base_addr, dev->irq, dev->dev_addr);
|
||||
netdev_info(dev, "Cadence %s at 0x%08lx irq %d (%pM)\n",
|
||||
macb_is_gem(bp) ? "GEM" : "MACB", dev->base_addr,
|
||||
dev->irq, dev->dev_addr);
|
||||
|
||||
phydev = bp->phy_dev;
|
||||
netdev_info(dev, "attached PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)\n",
|
||||
@ -1332,6 +1337,6 @@ module_init(macb_init);
|
||||
module_exit(macb_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("Atmel MACB Ethernet driver");
|
||||
MODULE_DESCRIPTION("Cadence MACB/GEM Ethernet driver");
|
||||
MODULE_AUTHOR("Haavard Skinnemoen (Atmel)");
|
||||
MODULE_ALIAS("platform:macb");
|
||||
|
@ -59,6 +59,15 @@
|
||||
#define MACB_TPQ 0x00bc
|
||||
#define MACB_USRIO 0x00c0
|
||||
#define MACB_WOL 0x00c4
|
||||
#define MACB_MID 0x00fc
|
||||
|
||||
/* GEM register offsets. */
|
||||
#define GEM_NCFGR 0x0004
|
||||
#define GEM_USRIO 0x000c
|
||||
#define GEM_HRB 0x0080
|
||||
#define GEM_HRT 0x0084
|
||||
#define GEM_SA1B 0x0088
|
||||
#define GEM_SA1T 0x008C
|
||||
|
||||
/* Bitfields in NCR */
|
||||
#define MACB_LB_OFFSET 0
|
||||
@ -228,6 +237,12 @@
|
||||
#define MACB_WOL_MTI_OFFSET 19
|
||||
#define MACB_WOL_MTI_SIZE 1
|
||||
|
||||
/* Bitfields in MID */
|
||||
#define MACB_IDNUM_OFFSET 16
|
||||
#define MACB_IDNUM_SIZE 16
|
||||
#define MACB_REV_OFFSET 0
|
||||
#define MACB_REV_SIZE 16
|
||||
|
||||
/* Constants for CLK */
|
||||
#define MACB_CLK_DIV8 0
|
||||
#define MACB_CLK_DIV16 1
|
||||
@ -254,11 +269,52 @@
|
||||
<< MACB_##name##_OFFSET)) \
|
||||
| MACB_BF(name,value))
|
||||
|
||||
#define GEM_BIT(name) \
|
||||
(1 << GEM_##name##_OFFSET)
|
||||
#define GEM_BF(name, value) \
|
||||
(((value) & ((1 << GEM_##name##_SIZE) - 1)) \
|
||||
<< GEM_##name##_OFFSET)
|
||||
#define GEM_BFEXT(name, value)\
|
||||
(((value) >> GEM_##name##_OFFSET) \
|
||||
& ((1 << GEM_##name##_SIZE) - 1))
|
||||
#define GEM_BFINS(name, value, old) \
|
||||
(((old) & ~(((1 << GEM_##name##_SIZE) - 1) \
|
||||
<< GEM_##name##_OFFSET)) \
|
||||
| GEM_BF(name, value))
|
||||
|
||||
/* Register access macros */
|
||||
#define macb_readl(port,reg) \
|
||||
__raw_readl((port)->regs + MACB_##reg)
|
||||
#define macb_writel(port,reg,value) \
|
||||
__raw_writel((value), (port)->regs + MACB_##reg)
|
||||
#define gem_readl(port, reg) \
|
||||
__raw_readl((port)->regs + GEM_##reg)
|
||||
#define gem_writel(port, reg, value) \
|
||||
__raw_writel((value), (port)->regs + GEM_##reg)
|
||||
|
||||
/*
|
||||
* Conditional GEM/MACB macros. These perform the operation to the correct
|
||||
* register dependent on whether the device is a GEM or a MACB. For registers
|
||||
* and bitfields that are common across both devices, use macb_{read,write}l
|
||||
* to avoid the cost of the conditional.
|
||||
*/
|
||||
#define macb_or_gem_writel(__bp, __reg, __value) \
|
||||
({ \
|
||||
if (macb_is_gem((__bp))) \
|
||||
gem_writel((__bp), __reg, __value); \
|
||||
else \
|
||||
macb_writel((__bp), __reg, __value); \
|
||||
})
|
||||
|
||||
#define macb_or_gem_readl(__bp, __reg) \
|
||||
({ \
|
||||
u32 __v; \
|
||||
if (macb_is_gem((__bp))) \
|
||||
__v = gem_readl((__bp), __reg); \
|
||||
else \
|
||||
__v = macb_readl((__bp), __reg); \
|
||||
__v; \
|
||||
})
|
||||
|
||||
struct dma_desc {
|
||||
u32 addr;
|
||||
@ -391,4 +447,9 @@ struct macb {
|
||||
unsigned int duplex;
|
||||
};
|
||||
|
||||
static inline bool macb_is_gem(struct macb *bp)
|
||||
{
|
||||
return MACB_BFEXT(IDNUM, macb_readl(bp, MID)) == 0x2;
|
||||
}
|
||||
|
||||
#endif /* _MACB_H */
|
||||
|
Loading…
Reference in New Issue
Block a user