[PATCH 4/8] macb: initial support for Cadence GEM

Jamie Iles jamie at jamieiles.com
Thu Mar 10 05:10:39 EST 2011


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 adds a new platform driver for gem which sets allows the driver to
tell at runtime whether it is targetting a GEM device.

Signed-off-by: Jamie Iles <jamie at jamieiles.com>
---
 drivers/net/Kconfig |    8 ++++--
 drivers/net/macb.c  |   53 ++++++++++++++++++++++++++++++++++++++++++--------
 drivers/net/macb.h  |   18 +++++++++++++++++
 3 files changed, 67 insertions(+), 12 deletions(-)

diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 6bd5caa..6de335a 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -223,12 +223,14 @@ menuconfig NET_ETHERNET
 if NET_ETHERNET
 
 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.
diff --git a/drivers/net/macb.c b/drivers/net/macb.c
index 5d676ad..204afa6 100644
--- a/drivers/net/macb.c
+++ b/drivers/net/macb.c
@@ -1,5 +1,5 @@
 /*
- * Atmel MACB Ethernet Controller driver
+ * Cadence MACB/GEM Ethernet Controller driver
  *
  * Copyright (C) 2004-2006 Atmel Corporation
  *
@@ -7,7 +7,6 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-
 #define pr_fmt(fmt) "macb: " fmt
 #include <linux/clk.h>
 #include <linux/module.h>
@@ -1108,7 +1107,7 @@ static const struct net_device_ops macb_netdev_ops = {
 #define PCLK_NAME	"pclk"
 #endif
 
-static int __init macb_probe(struct platform_device *pdev)
+static int __macb_probe(struct platform_device *pdev, int is_gem)
 {
 	struct resource *regs;
 	struct net_device *dev;
@@ -1147,6 +1146,7 @@ static int __init macb_probe(struct platform_device *pdev)
 	bp = netdev_priv(dev);
 	bp->pdev = pdev;
 	bp->dev = dev;
+	bp->is_gem = is_gem;
 
 	spin_lock_init(&bp->lock);
 
@@ -1230,8 +1230,9 @@ static int __init macb_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, dev);
 
-	pr_info("%s: Atmel MACB at 0x%08lx irq %d (%pM)\n",
-		dev->name, dev->base_addr, dev->irq, dev->dev_addr);
+	pr_info("%s: Cadence %s at 0x%08lx irq %d (%pM)\n",
+		dev->name, bp->is_gem ? "GEM" : "MACB", dev->base_addr,
+		dev->irq, dev->dev_addr);
 
 	phydev = bp->phy_dev;
 	pr_info("%s: attached PHY driver [%s] "
@@ -1261,7 +1262,17 @@ err_out:
 	return err;
 }
 
-static int __exit macb_remove(struct platform_device *pdev)
+static int __devinit macb_probe(struct platform_device *pdev)
+{
+	return __macb_probe(pdev, 0);
+}
+
+static int __devinit gem_probe(struct platform_device *pdev)
+{
+	return __macb_probe(pdev, 1);
+}
+
+static int __devexit macb_remove(struct platform_device *pdev)
 {
 	struct net_device *dev;
 	struct macb *bp;
@@ -1328,7 +1339,8 @@ static int macb_resume(struct platform_device *pdev)
 #endif
 
 static struct platform_driver macb_driver = {
-	.remove		= __exit_p(macb_remove),
+	.probe		= macb_probe,
+	.remove		= __devexit_p(macb_remove),
 	.suspend	= macb_suspend,
 	.resume		= macb_resume,
 	.driver		= {
@@ -1337,20 +1349,43 @@ static struct platform_driver macb_driver = {
 	},
 };
 
+static struct platform_driver gem_driver = {
+	.probe		= gem_probe,
+	.remove		= __devexit_p(macb_remove),
+	.suspend	= macb_suspend,
+	.resume		= macb_resume,
+	.driver		= {
+		.name		= "gem",
+		.owner	= THIS_MODULE,
+	},
+};
+
 static int __init macb_init(void)
 {
-	return platform_driver_probe(&macb_driver, macb_probe);
+	int ret;
+
+	ret = platform_driver_register(&macb_driver);
+	if (ret)
+		return ret;
+
+	ret = platform_driver_register(&gem_driver);
+	if (ret)
+		platform_driver_unregister(&macb_driver);
+
+	return ret;
+
 }
 
 static void __exit macb_exit(void)
 {
 	platform_driver_unregister(&macb_driver);
+	platform_driver_unregister(&gem_driver);
 }
 
 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 <hskinnemoen at atmel.com>");
 MODULE_ALIAS("platform:macb");
diff --git a/drivers/net/macb.h b/drivers/net/macb.h
index d3212f6..f838615 100644
--- a/drivers/net/macb.h
+++ b/drivers/net/macb.h
@@ -254,11 +254,28 @@
 		    << 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)
 
 struct dma_desc {
 	u32	addr;
@@ -360,6 +377,7 @@ struct macb_stats {
 
 struct macb {
 	void __iomem		*regs;
+	int			is_gem;
 
 	unsigned int		rx_tail;
 	struct dma_desc		*rx_ring;
-- 
1.7.4




More information about the linux-arm-kernel mailing list