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 | |
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')
-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 */ |