diff options
| author | Jamie Iles <jamie.iles@mathembedded.com> | 2011-11-08 05:12:32 -0500 |
|---|---|---|
| committer | Jamie Iles <jamie@jamieiles.com> | 2011-11-22 10:21:17 -0500 |
| commit | f75ba50bdc2bcfab591bdf903312557033d0ac68 (patch) | |
| tree | 4ccc618be2fb9f998eed75549ca69b31712b0d0e /drivers/net | |
| parent | c220f8cd01198552a616c4216f2a8e719fdb5fd9 (diff) | |
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>
Diffstat (limited to 'drivers/net')
| -rw-r--r-- | drivers/net/ethernet/Makefile | 2 | ||||
| -rw-r--r-- | drivers/net/ethernet/cadence/Kconfig | 16 | ||||
| -rw-r--r-- | drivers/net/ethernet/cadence/macb.c | 43 | ||||
| -rw-r--r-- | drivers/net/ethernet/cadence/macb.h | 61 |
4 files changed, 95 insertions, 27 deletions
diff --git a/drivers/net/ethernet/Makefile b/drivers/net/ethernet/Makefile index be5dde040261..94b7f287d6c5 100644 --- a/drivers/net/ethernet/Makefile +++ b/drivers/net/ethernet/Makefile | |||
| @@ -10,7 +10,7 @@ obj-$(CONFIG_NET_VENDOR_ALTEON) += alteon/ | |||
| 10 | obj-$(CONFIG_NET_VENDOR_AMD) += amd/ | 10 | obj-$(CONFIG_NET_VENDOR_AMD) += amd/ |
| 11 | obj-$(CONFIG_NET_VENDOR_APPLE) += apple/ | 11 | obj-$(CONFIG_NET_VENDOR_APPLE) += apple/ |
| 12 | obj-$(CONFIG_NET_VENDOR_ATHEROS) += atheros/ | 12 | obj-$(CONFIG_NET_VENDOR_ATHEROS) += atheros/ |
| 13 | obj-$(CONFIG_NET_ATMEL) += cadence/ | 13 | obj-$(CONFIG_NET_CADENCE) += cadence/ |
| 14 | obj-$(CONFIG_NET_BFIN) += adi/ | 14 | obj-$(CONFIG_NET_BFIN) += adi/ |
| 15 | obj-$(CONFIG_NET_VENDOR_BROADCOM) += broadcom/ | 15 | obj-$(CONFIG_NET_VENDOR_BROADCOM) += broadcom/ |
| 16 | obj-$(CONFIG_NET_VENDOR_BROCADE) += brocade/ | 16 | obj-$(CONFIG_NET_VENDOR_BROCADE) += brocade/ |
diff --git a/drivers/net/ethernet/cadence/Kconfig b/drivers/net/ethernet/cadence/Kconfig index 98849a1fc749..a2e150059bc7 100644 --- a/drivers/net/ethernet/cadence/Kconfig +++ b/drivers/net/ethernet/cadence/Kconfig | |||
| @@ -5,8 +5,8 @@ | |||
| 5 | config HAVE_NET_MACB | 5 | config HAVE_NET_MACB |
| 6 | bool | 6 | bool |
| 7 | 7 | ||
| 8 | config NET_ATMEL | 8 | config NET_CADENCE |
| 9 | bool "Atmel devices" | 9 | bool "Cadence devices" |
| 10 | depends on HAVE_NET_MACB || (ARM && ARCH_AT91RM9200) | 10 | depends on HAVE_NET_MACB || (ARM && ARCH_AT91RM9200) |
| 11 | ---help--- | 11 | ---help--- |
| 12 | If you have a network (Ethernet) card belonging to this class, say Y. | 12 | If you have a network (Ethernet) card belonging to this class, say Y. |
| @@ -20,7 +20,7 @@ config NET_ATMEL | |||
| 20 | the remaining Atmel network card questions. If you say Y, you will be | 20 | the remaining Atmel network card questions. If you say Y, you will be |
| 21 | asked for your specific card in the following questions. | 21 | asked for your specific card in the following questions. |
| 22 | 22 | ||
| 23 | if NET_ATMEL | 23 | if NET_CADENCE |
| 24 | 24 | ||
| 25 | config ARM_AT91_ETHER | 25 | config ARM_AT91_ETHER |
| 26 | tristate "AT91RM9200 Ethernet support" | 26 | tristate "AT91RM9200 Ethernet support" |
| @@ -32,14 +32,16 @@ config ARM_AT91_ETHER | |||
| 32 | ethernet support, then you should always answer Y to this. | 32 | ethernet support, then you should always answer Y to this. |
| 33 | 33 | ||
| 34 | config MACB | 34 | config MACB |
| 35 | tristate "Atmel MACB support" | 35 | tristate "Cadence MACB/GEM support" |
| 36 | depends on HAVE_NET_MACB | 36 | depends on HAVE_NET_MACB |
| 37 | select PHYLIB | 37 | select PHYLIB |
| 38 | ---help--- | 38 | ---help--- |
| 39 | The Atmel MACB ethernet interface is found on many AT32 and AT91 | 39 | The Cadence MACB ethernet interface is found on many Atmel AT32 and |
| 40 | parts. Say Y to include support for the MACB chip. | 40 | AT91 parts. This driver also supports the Cadence GEM (Gigabit |
| 41 | Ethernet MAC found in some ARM SoC devices). Note: the Gigabit mode | ||
| 42 | is not yet supported. Say Y to include support for the MACB/GEM chip. | ||
| 41 | 43 | ||
| 42 | To compile this driver as a module, choose M here: the module | 44 | To compile this driver as a module, choose M here: the module |
| 43 | will be called macb. | 45 | will be called macb. |
| 44 | 46 | ||
| 45 | endif # NET_ATMEL | 47 | endif # NET_CADENCE |
diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c index aa1d597091a8..4e61a8610d6a 100644 --- a/drivers/net/ethernet/cadence/macb.c +++ b/drivers/net/ethernet/cadence/macb.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Atmel MACB Ethernet Controller driver | 2 | * Cadence MACB/GEM Ethernet Controller driver |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2004-2006 Atmel Corporation | 4 | * Copyright (C) 2004-2006 Atmel Corporation |
| 5 | * | 5 | * |
| @@ -59,9 +59,9 @@ static void __macb_set_hwaddr(struct macb *bp) | |||
| 59 | u16 top; | 59 | u16 top; |
| 60 | 60 | ||
| 61 | bottom = cpu_to_le32(*((u32 *)bp->dev->dev_addr)); | 61 | bottom = cpu_to_le32(*((u32 *)bp->dev->dev_addr)); |
| 62 | macb_writel(bp, SA1B, bottom); | 62 | macb_or_gem_writel(bp, SA1B, bottom); |
| 63 | top = cpu_to_le16(*((u16 *)(bp->dev->dev_addr + 4))); | 63 | top = cpu_to_le16(*((u16 *)(bp->dev->dev_addr + 4))); |
| 64 | macb_writel(bp, SA1T, top); | 64 | macb_or_gem_writel(bp, SA1T, top); |
| 65 | } | 65 | } |
| 66 | 66 | ||
| 67 | static void __init macb_get_hwaddr(struct macb *bp) | 67 | static void __init macb_get_hwaddr(struct macb *bp) |
| @@ -70,8 +70,8 @@ static void __init macb_get_hwaddr(struct macb *bp) | |||
| 70 | u16 top; | 70 | u16 top; |
| 71 | u8 addr[6]; | 71 | u8 addr[6]; |
| 72 | 72 | ||
| 73 | bottom = macb_readl(bp, SA1B); | 73 | bottom = macb_or_gem_readl(bp, SA1B); |
| 74 | top = macb_readl(bp, SA1T); | 74 | top = macb_or_gem_readl(bp, SA1T); |
| 75 | 75 | ||
| 76 | addr[0] = bottom & 0xff; | 76 | addr[0] = bottom & 0xff; |
| 77 | addr[1] = (bottom >> 8) & 0xff; | 77 | addr[1] = (bottom >> 8) & 0xff; |
| @@ -580,7 +580,10 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id) | |||
| 580 | 580 | ||
| 581 | if (status & MACB_BIT(ISR_ROVR)) { | 581 | if (status & MACB_BIT(ISR_ROVR)) { |
| 582 | /* We missed at least one packet */ | 582 | /* We missed at least one packet */ |
| 583 | bp->hw_stats.rx_overruns++; | 583 | if (macb_is_gem(bp)) |
| 584 | bp->hw_stats.gem.rx_overruns++; | ||
| 585 | else | ||
| 586 | bp->hw_stats.macb.rx_overruns++; | ||
| 584 | } | 587 | } |
| 585 | 588 | ||
| 586 | if (status & MACB_BIT(HRESP)) { | 589 | if (status & MACB_BIT(HRESP)) { |
| @@ -902,8 +905,8 @@ static void macb_sethashtable(struct net_device *dev) | |||
| 902 | mc_filter[bitnr >> 5] |= 1 << (bitnr & 31); | 905 | mc_filter[bitnr >> 5] |= 1 << (bitnr & 31); |
| 903 | } | 906 | } |
| 904 | 907 | ||
| 905 | macb_writel(bp, HRB, mc_filter[0]); | 908 | macb_or_gem_writel(bp, HRB, mc_filter[0]); |
| 906 | macb_writel(bp, HRT, mc_filter[1]); | 909 | macb_or_gem_writel(bp, HRT, mc_filter[1]); |
| 907 | } | 910 | } |
| 908 | 911 | ||
| 909 | /* | 912 | /* |
| @@ -925,8 +928,8 @@ static void macb_set_rx_mode(struct net_device *dev) | |||
| 925 | 928 | ||
| 926 | if (dev->flags & IFF_ALLMULTI) { | 929 | if (dev->flags & IFF_ALLMULTI) { |
| 927 | /* Enable all multicast mode */ | 930 | /* Enable all multicast mode */ |
| 928 | macb_writel(bp, HRB, -1); | 931 | macb_or_gem_writel(bp, HRB, -1); |
| 929 | macb_writel(bp, HRT, -1); | 932 | macb_or_gem_writel(bp, HRT, -1); |
| 930 | cfg |= MACB_BIT(NCFGR_MTI); | 933 | cfg |= MACB_BIT(NCFGR_MTI); |
| 931 | } else if (!netdev_mc_empty(dev)) { | 934 | } else if (!netdev_mc_empty(dev)) { |
| 932 | /* Enable specific multicasts */ | 935 | /* Enable specific multicasts */ |
| @@ -934,8 +937,8 @@ static void macb_set_rx_mode(struct net_device *dev) | |||
| 934 | cfg |= MACB_BIT(NCFGR_MTI); | 937 | cfg |= MACB_BIT(NCFGR_MTI); |
| 935 | } else if (dev->flags & (~IFF_ALLMULTI)) { | 938 | } else if (dev->flags & (~IFF_ALLMULTI)) { |
| 936 | /* Disable all multicast mode */ | 939 | /* Disable all multicast mode */ |
| 937 | macb_writel(bp, HRB, 0); | 940 | macb_or_gem_writel(bp, HRB, 0); |
| 938 | macb_writel(bp, HRT, 0); | 941 | macb_or_gem_writel(bp, HRT, 0); |
| 939 | cfg &= ~MACB_BIT(NCFGR_MTI); | 942 | cfg &= ~MACB_BIT(NCFGR_MTI); |
| 940 | } | 943 | } |
| 941 | 944 | ||
| @@ -1196,15 +1199,16 @@ static int __init macb_probe(struct platform_device *pdev) | |||
| 1196 | 1199 | ||
| 1197 | if (pdata && pdata->is_rmii) | 1200 | if (pdata && pdata->is_rmii) |
| 1198 | #if defined(CONFIG_ARCH_AT91) | 1201 | #if defined(CONFIG_ARCH_AT91) |
| 1199 | macb_writel(bp, USRIO, (MACB_BIT(RMII) | MACB_BIT(CLKEN)) ); | 1202 | macb_or_gem_writel(bp, USRIO, (MACB_BIT(RMII) | |
| 1203 | MACB_BIT(CLKEN))); | ||
| 1200 | #else | 1204 | #else |
| 1201 | macb_writel(bp, USRIO, 0); | 1205 | macb_or_gem_writel(bp, USRIO, 0); |
| 1202 | #endif | 1206 | #endif |
| 1203 | else | 1207 | else |
| 1204 | #if defined(CONFIG_ARCH_AT91) | 1208 | #if defined(CONFIG_ARCH_AT91) |
| 1205 | macb_writel(bp, USRIO, MACB_BIT(CLKEN)); | 1209 | macb_or_gem_writel(bp, USRIO, MACB_BIT(CLKEN)); |
| 1206 | #else | 1210 | #else |
| 1207 | macb_writel(bp, USRIO, MACB_BIT(MII)); | 1211 | macb_or_gem_writel(bp, USRIO, MACB_BIT(MII)); |
| 1208 | #endif | 1212 | #endif |
| 1209 | 1213 | ||
| 1210 | bp->tx_pending = DEF_TX_RING_PENDING; | 1214 | bp->tx_pending = DEF_TX_RING_PENDING; |
| @@ -1221,8 +1225,9 @@ static int __init macb_probe(struct platform_device *pdev) | |||
| 1221 | 1225 | ||
| 1222 | platform_set_drvdata(pdev, dev); | 1226 | platform_set_drvdata(pdev, dev); |
| 1223 | 1227 | ||
| 1224 | netdev_info(dev, "Atmel MACB at 0x%08lx irq %d (%pM)\n", | 1228 | netdev_info(dev, "Cadence %s at 0x%08lx irq %d (%pM)\n", |
| 1225 | dev->base_addr, dev->irq, dev->dev_addr); | 1229 | macb_is_gem(bp) ? "GEM" : "MACB", dev->base_addr, |
| 1230 | dev->irq, dev->dev_addr); | ||
| 1226 | 1231 | ||
| 1227 | phydev = bp->phy_dev; | 1232 | phydev = bp->phy_dev; |
| 1228 | netdev_info(dev, "attached PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)\n", | 1233 | netdev_info(dev, "attached PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)\n", |
| @@ -1332,6 +1337,6 @@ module_init(macb_init); | |||
| 1332 | module_exit(macb_exit); | 1337 | module_exit(macb_exit); |
| 1333 | 1338 | ||
| 1334 | MODULE_LICENSE("GPL"); | 1339 | MODULE_LICENSE("GPL"); |
| 1335 | MODULE_DESCRIPTION("Atmel MACB Ethernet driver"); | 1340 | MODULE_DESCRIPTION("Cadence MACB/GEM Ethernet driver"); |
| 1336 | MODULE_AUTHOR("Haavard Skinnemoen (Atmel)"); | 1341 | MODULE_AUTHOR("Haavard Skinnemoen (Atmel)"); |
| 1337 | MODULE_ALIAS("platform:macb"); | 1342 | MODULE_ALIAS("platform:macb"); |
diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h index d3212f6db703..d50057c244b2 100644 --- a/drivers/net/ethernet/cadence/macb.h +++ b/drivers/net/ethernet/cadence/macb.h | |||
| @@ -59,6 +59,15 @@ | |||
| 59 | #define MACB_TPQ 0x00bc | 59 | #define MACB_TPQ 0x00bc |
| 60 | #define MACB_USRIO 0x00c0 | 60 | #define MACB_USRIO 0x00c0 |
| 61 | #define MACB_WOL 0x00c4 | 61 | #define MACB_WOL 0x00c4 |
| 62 | #define MACB_MID 0x00fc | ||
| 63 | |||
| 64 | /* GEM register offsets. */ | ||
| 65 | #define GEM_NCFGR 0x0004 | ||
| 66 | #define GEM_USRIO 0x000c | ||
| 67 | #define GEM_HRB 0x0080 | ||
| 68 | #define GEM_HRT 0x0084 | ||
| 69 | #define GEM_SA1B 0x0088 | ||
| 70 | #define GEM_SA1T 0x008C | ||
| 62 | 71 | ||
| 63 | /* Bitfields in NCR */ | 72 | /* Bitfields in NCR */ |
| 64 | #define MACB_LB_OFFSET 0 | 73 | #define MACB_LB_OFFSET 0 |
| @@ -228,6 +237,12 @@ | |||
| 228 | #define MACB_WOL_MTI_OFFSET 19 | 237 | #define MACB_WOL_MTI_OFFSET 19 |
| 229 | #define MACB_WOL_MTI_SIZE 1 | 238 | #define MACB_WOL_MTI_SIZE 1 |
| 230 | 239 | ||
| 240 | /* Bitfields in MID */ | ||
| 241 | #define MACB_IDNUM_OFFSET 16 | ||
| 242 | #define MACB_IDNUM_SIZE 16 | ||
| 243 | #define MACB_REV_OFFSET 0 | ||
| 244 | #define MACB_REV_SIZE 16 | ||
| 245 | |||
| 231 | /* Constants for CLK */ | 246 | /* Constants for CLK */ |
| 232 | #define MACB_CLK_DIV8 0 | 247 | #define MACB_CLK_DIV8 0 |
| 233 | #define MACB_CLK_DIV16 1 | 248 | #define MACB_CLK_DIV16 1 |
| @@ -254,11 +269,52 @@ | |||
| 254 | << MACB_##name##_OFFSET)) \ | 269 | << MACB_##name##_OFFSET)) \ |
| 255 | | MACB_BF(name,value)) | 270 | | MACB_BF(name,value)) |
| 256 | 271 | ||
| 272 | #define GEM_BIT(name) \ | ||
| 273 | (1 << GEM_##name##_OFFSET) | ||
| 274 | #define GEM_BF(name, value) \ | ||
| 275 | (((value) & ((1 << GEM_##name##_SIZE) - 1)) \ | ||
| 276 | << GEM_##name##_OFFSET) | ||
| 277 | #define GEM_BFEXT(name, value)\ | ||
| 278 | (((value) >> GEM_##name##_OFFSET) \ | ||
| 279 | & ((1 << GEM_##name##_SIZE) - 1)) | ||
| 280 | #define GEM_BFINS(name, value, old) \ | ||
| 281 | (((old) & ~(((1 << GEM_##name##_SIZE) - 1) \ | ||
| 282 | << GEM_##name##_OFFSET)) \ | ||
| 283 | | GEM_BF(name, value)) | ||
| 284 | |||
| 257 | /* Register access macros */ | 285 | /* Register access macros */ |
| 258 | #define macb_readl(port,reg) \ | 286 | #define macb_readl(port,reg) \ |
| 259 | __raw_readl((port)->regs + MACB_##reg) | 287 | __raw_readl((port)->regs + MACB_##reg) |
| 260 | #define macb_writel(port,reg,value) \ | 288 | #define macb_writel(port,reg,value) \ |
| 261 | __raw_writel((value), (port)->regs + MACB_##reg) | 289 | __raw_writel((value), (port)->regs + MACB_##reg) |
| 290 | #define gem_readl(port, reg) \ | ||
| 291 | __raw_readl((port)->regs + GEM_##reg) | ||
| 292 | #define gem_writel(port, reg, value) \ | ||
| 293 | __raw_writel((value), (port)->regs + GEM_##reg) | ||
| 294 | |||
| 295 | /* | ||
| 296 | * Conditional GEM/MACB macros. These perform the operation to the correct | ||
| 297 | * register dependent on whether the device is a GEM or a MACB. For registers | ||
| 298 | * and bitfields that are common across both devices, use macb_{read,write}l | ||
| 299 | * to avoid the cost of the conditional. | ||
| 300 | */ | ||
| 301 | #define macb_or_gem_writel(__bp, __reg, __value) \ | ||
| 302 | ({ \ | ||
| 303 | if (macb_is_gem((__bp))) \ | ||
| 304 | gem_writel((__bp), __reg, __value); \ | ||
| 305 | else \ | ||
| 306 | macb_writel((__bp), __reg, __value); \ | ||
| 307 | }) | ||
| 308 | |||
| 309 | #define macb_or_gem_readl(__bp, __reg) \ | ||
| 310 | ({ \ | ||
| 311 | u32 __v; \ | ||
| 312 | if (macb_is_gem((__bp))) \ | ||
| 313 | __v = gem_readl((__bp), __reg); \ | ||
| 314 | else \ | ||
| 315 | __v = macb_readl((__bp), __reg); \ | ||
| 316 | __v; \ | ||
| 317 | }) | ||
| 262 | 318 | ||
| 263 | struct dma_desc { | 319 | struct dma_desc { |
| 264 | u32 addr; | 320 | u32 addr; |
| @@ -391,4 +447,9 @@ struct macb { | |||
| 391 | unsigned int duplex; | 447 | unsigned int duplex; |
| 392 | }; | 448 | }; |
| 393 | 449 | ||
| 450 | static inline bool macb_is_gem(struct macb *bp) | ||
| 451 | { | ||
| 452 | return MACB_BFEXT(IDNUM, macb_readl(bp, MID)) == 0x2; | ||
| 453 | } | ||
| 454 | |||
| 394 | #endif /* _MACB_H */ | 455 | #endif /* _MACB_H */ |
