[linux-yocto] [PATCH 10/94] drivers/net/ethernet: add ACP wrappers back into kernel

Paul Butler butler.paul at gmail.com
Thu Nov 7 17:12:24 PST 2013


From: David Mercado <david.mercado at windriver.com>

This patch adds the LSI ACP wrapper routines back into the kernel. These
were previously removed as part of the acp34xx Ethernet driver updates,
but are needed for the LSI RTE application.

The wrappers are restored at arch/powerpc/sysdev/lsi_acp_wrappers.c

Signed-off-by: David Mercado <david.mercado at windriver.com>
---
 arch/powerpc/include/asm/lsi/acp_ncr.h |   3 +
 arch/powerpc/sysdev/Makefile           |   2 +-
 arch/powerpc/sysdev/lsi_acp_wrappers.c | 325 +++++++++++++++++++++++++++++++++
 drivers/net/ethernet/lsi/lsi_acp_net.c | 117 +-----------
 drivers/net/ethernet/lsi/lsi_acp_net.h |   2 -
 5 files changed, 333 insertions(+), 116 deletions(-)
 create mode 100644 arch/powerpc/sysdev/lsi_acp_wrappers.c

diff --git a/arch/powerpc/include/asm/lsi/acp_ncr.h b/arch/powerpc/include/asm/lsi/acp_ncr.h
index a7399e7..1a08f07 100644
--- a/arch/powerpc/include/asm/lsi/acp_ncr.h
+++ b/arch/powerpc/include/asm/lsi/acp_ncr.h
@@ -39,4 +39,7 @@ int ncr_write(unsigned long, unsigned long, int, void *);
 
 int is_asic(void);
 
+extern int acp_mdio_read(unsigned long, unsigned long, unsigned short *);
+extern int acp_mdio_write(unsigned long, unsigned long, unsigned short);
+
 #endif /*  __DRIVERS_LSI_ACP_NCR_H */
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index 6354d1c..a95b59f 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -73,4 +73,4 @@ obj-$(CONFIG_PPC_XICS)		+= xics/
 
 obj-$(CONFIG_GE_FPGA)		+= ge/
 
-obj-$(CONFIG_ACP)		+= lsi_acp_ncr.o
+obj-$(CONFIG_ACP)		+= lsi_acp_ncr.o lsi_acp_wrappers.o
diff --git a/arch/powerpc/sysdev/lsi_acp_wrappers.c b/arch/powerpc/sysdev/lsi_acp_wrappers.c
new file mode 100644
index 0000000..910ed25
--- /dev/null
+++ b/arch/powerpc/sysdev/lsi_acp_wrappers.c
@@ -0,0 +1,325 @@
+/*
+ * arch/powerpc/sysdev/lsi_acp_wrappers.c
+ *
+ * Copyright (C) 2013 LSI
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307	 USA
+ */
+
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/sched.h>
+#include <linux/of.h>
+#include <linux/io.h>
+#include <asm/irq.h>
+#include <asm/lsi/acp_ncr.h>
+
+MODULE_AUTHOR("LSI Corporation");
+MODULE_DESCRIPTION("ACP Wrappers");
+MODULE_LICENSE("GPL");
+
+/*
+  ============================================================================
+  ============================================================================
+  MDIO Access
+  ============================================================================
+  ============================================================================
+*/
+
+
+static unsigned long mdio_base;
+DEFINE_SPINLOCK(mdio_lock);
+
+#define MDIO_CONTROL_RD_DATA ((void *)(mdio_base + 0x0))
+#define MDIO_STATUS_RD_DATA  ((void *)(mdio_base + 0x4))
+#define MDIO_CLK_OFFSET      ((void *)(mdio_base + 0x8))
+#define MDIO_CLK_PERIOD      ((void *)(mdio_base + 0xc))
+
+/*
+ * -------------------------------------------------------------------------
+ * acp_mdio_read
+ */
+
+int acp_mdio_read(unsigned long address, unsigned long offset,
+		  unsigned short *value)
+{
+	unsigned long command = 0;
+	unsigned long status;
+	unsigned long flags;
+
+	spin_lock_irqsave(&mdio_lock, flags);
+
+	/* Set the mdio_busy (status) bit. */
+	status = in_le32(MDIO_STATUS_RD_DATA);
+	status |= 0x40000000;
+	out_le32(MDIO_STATUS_RD_DATA, status);
+
+	/* Write the command.*/
+	command |= 0x10000000;	/* op_code: read */
+	command |= (address & 0x1f) << 16; /* port_addr (target device) */
+	command |= (offset & 0x1f) << 21; /* device_addr (target register) */
+	out_le32(MDIO_CONTROL_RD_DATA, command);
+
+	/* Wait for the mdio_busy (status) bit to clear. */
+	do {
+		status = in_le32(MDIO_STATUS_RD_DATA);
+	} while (0 != (status & 0x40000000));
+
+	/* Wait for the mdio_busy (control) bit to clear. */
+	do {
+		command = in_le32(MDIO_CONTROL_RD_DATA);
+	} while (0 != (command & 0x80000000));
+
+	*value = (unsigned short)(command & 0xffff);
+
+	spin_unlock_irqrestore(&mdio_lock, flags);
+
+	return 0;
+}
+EXPORT_SYMBOL(acp_mdio_read);
+
+/*
+ * -------------------------------------------------------------------------
+ * acp_mdio_write
+ */
+
+int acp_mdio_write(unsigned long address, unsigned long offset,
+		   unsigned short value)
+{
+	unsigned long command = 0;
+	unsigned long status;
+	unsigned long flags;
+
+	spin_lock_irqsave(&mdio_lock, flags);
+
+	/* Wait for mdio_busy (control) to be clear. */
+	do {
+		command = in_le32(MDIO_CONTROL_RD_DATA);
+	} while (0 != (command & 0x80000000));
+
+	/* Set the mdio_busy (status) bit. */
+	status = in_le32(MDIO_STATUS_RD_DATA);
+	status |= 0x40000000;
+	out_le32(MDIO_STATUS_RD_DATA, status);
+
+	/* Write the command. */
+	command = 0x08000000;	/* op_code: write */
+	command |= (address & 0x1f) << 16; /* port_addr (target device) */
+	command |= (offset & 0x1f) << 21; /* device_addr (target register) */
+	command |= (value & 0xffff); /* value */
+	out_le32(MDIO_CONTROL_RD_DATA, command);
+
+	/* Wait for the mdio_busy (status) bit to clear. */
+	do {
+		status = in_le32(MDIO_STATUS_RD_DATA);
+	} while (0 != (status & 0x40000000));
+
+	/* Wait for the mdio_busy (control) bit to clear. */
+	do {
+		command = in_le32(MDIO_CONTROL_RD_DATA);
+	} while (0 != (command & 0x80000000));
+
+	spin_unlock_irqrestore(&mdio_lock, flags);
+
+	return 0;
+}
+EXPORT_SYMBOL(acp_mdio_write);
+
+/*
+ * -------------------------------------------------------------------------
+ * acp_mdio_initialize
+ */
+
+static int acp_mdio_initialize(void)
+{
+	if (is_asic()) {
+		out_le32(MDIO_CLK_OFFSET, 0x10);
+		out_le32(MDIO_CLK_PERIOD, 0x2c);
+	} else {
+		out_le32(MDIO_CLK_OFFSET, 0x05);
+		out_le32(MDIO_CLK_PERIOD, 0x0c);
+	}
+
+	return 0;
+}
+
+
+/*
+  ============================================================================
+  ============================================================================
+  Interrupts
+  ============================================================================
+  ============================================================================
+*/
+
+/*
+ * -------------------------------------------------------------------------
+ * acp_irq_create_mapping
+ */
+unsigned int acp_irq_create_mapping(struct irq_domain *host,
+				    irq_hw_number_t hwirq)
+{
+	unsigned int mapped_irq;
+
+	preempt_disable();
+	mapped_irq = irq_create_mapping(host, hwirq);
+	preempt_enable();
+
+	return mapped_irq;
+}
+EXPORT_SYMBOL(acp_irq_create_mapping);
+
+/*
+  ============================================================================
+  ============================================================================
+  Spin Locks
+  ============================================================================
+  ============================================================================
+*/
+
+/*
+ * -------------------------------------------------------------------------
+ * acp_spin_lock_init
+ */
+
+void acp_spin_lock_init(spinlock_t *lock)
+{
+	spin_lock_init(lock);
+}
+EXPORT_SYMBOL(acp_spin_lock_init);
+
+/*
+ * -------------------------------------------------------------------------
+ * acp_spin_lock
+ */
+
+void acp_spin_lock(spinlock_t *lock)
+{
+	spin_lock(lock);
+}
+EXPORT_SYMBOL(acp_spin_lock);
+
+/*
+ * -------------------------------------------------------------------------
+ * acp_spin_unlock
+ */
+
+void acp_spin_unlock(spinlock_t *lock)
+{
+	spin_unlock(lock);
+}
+EXPORT_SYMBOL(acp_spin_unlock);
+
+/*
+ * -------------------------------------------------------------------------
+ * acp_spin_lock_bh
+ */
+
+void acp_spin_lock_bh(spinlock_t *lock)
+{
+	spin_lock_bh(lock);
+}
+EXPORT_SYMBOL(acp_spin_lock_bh);
+
+/*
+ * -------------------------------------------------------------------------
+ * acp_spin_unlock_bh
+ */
+
+void acp_spin_unlock_bh(spinlock_t *lock)
+{
+	spin_unlock_bh(lock);
+}
+EXPORT_SYMBOL(acp_spin_unlock_bh);
+
+/*
+ * -------------------------------------------------------------------------
+ * acp_spin_lock_irqsave
+ */
+
+void acp_spin_lock_irqsave(spinlock_t *lock, unsigned long flags)
+{
+	spin_lock_irqsave(lock, flags);
+}
+EXPORT_SYMBOL(acp_spin_lock_irqsave);
+
+/*
+ * -------------------------------------------------------------------------
+ * acp_spin_unlock_irqrestore
+ */
+
+void acp_spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags)
+{
+	spin_unlock_irqrestore(lock, flags);
+}
+EXPORT_SYMBOL(acp_spin_unlock_irqrestore);
+
+/*
+ * -------------------------------------------------------------------------
+ * acp_wrappers_init
+ */
+
+int __init acp_wrappers_init(void)
+{
+	int rc = -1;
+	struct device_node *np = NULL;
+	const u32 *field;
+	u64 mdio_phys_address;
+	u32 mdio_size;
+
+	pr_info("Initializing ACP Wrappers.\n");
+
+	np = of_find_node_by_type(np, "network");
+
+	while (np && !of_device_is_compatible(np, "acp-femac"))
+		np = of_find_node_by_type(np, "network");
+
+	if (np) {
+		field = of_get_property(np, "enabled", NULL);
+
+		if (!field || (field && (0 == *field))) {
+			pr_warn("Networking is Not Enabled.\n");
+			goto acp_wrappers_init_done;
+		}
+
+		field = of_get_property(np, "mdio-reg", NULL);
+
+		if (!field) {
+			pr_err("Couldn't get \"mdio-reg\" property.\n");
+		} else {
+			mdio_phys_address = of_translate_address(np, field);
+			mdio_size = field[1];
+			rc = 0;
+		}
+	}
+
+	if (0 != rc) {
+		mdio_phys_address = 0x002000409000ULL;
+		mdio_size = 0x1000;
+		pr_warn("** MDIO Address Not Specified in Device Tree.\n");
+	}
+
+	mdio_base = (unsigned long)ioremap(mdio_phys_address, mdio_size);
+	rc = acp_mdio_initialize();
+
+	if (0 != rc)
+		pr_err("MDIO Initiailzation Failed!\n");
+
+acp_wrappers_init_done:
+
+	return 0;
+}
+
+module_init(acp_wrappers_init);
diff --git a/drivers/net/ethernet/lsi/lsi_acp_net.c b/drivers/net/ethernet/lsi/lsi_acp_net.c
index 21153bf..605a431 100644
--- a/drivers/net/ethernet/lsi/lsi_acp_net.c
+++ b/drivers/net/ethernet/lsi/lsi_acp_net.c
@@ -72,7 +72,6 @@
 #define LSI_MDIO_NAME          "acp-femac-mdio"
 #define LSI_DRV_VERSION        "2013-04-30"
 
-
 MODULE_AUTHOR("John Jacques");
 MODULE_DESCRIPTION("LSI ACP-FEMAC Ethernet driver");
 MODULE_LICENSE("GPL");
@@ -83,37 +82,6 @@ static void *tx_base;
 static void *dma_base;
 
 /*
-  =============================================================================
-  MDIO / PHY
-  =============================================================================
-*/
-
-#define MDIO_CONTROL_RD_DATA ((void *)(pdata->mdio_base + 0x0))
-#define MDIO_STATUS_RD_DATA  ((void *)(pdata->mdio_base + 0x4))
-#define MDIO_CLK_OFFSET      ((void *)(pdata->mdio_base + 0x8))
-#define MDIO_CLK_PERIOD      ((void *)(pdata->mdio_base + 0xc))
-
-/*
- * ----------------------------------------------------------------------
- * appnic_mdio_initialize
- */
-
-static void appnic_mdio_initialize(struct net_device *dev)
-{
-	struct appnic_device *pdata = netdev_priv(dev);
-
-	if (is_asic()) {
-		out_le32(MDIO_CLK_OFFSET, 0x10);
-		out_le32(MDIO_CLK_PERIOD, 0x2c);
-	} else {
-		out_le32(MDIO_CLK_OFFSET, 0x05);
-		out_le32(MDIO_CLK_PERIOD, 0x0c);
-	}
-
-	return;
-}
-
-/*
  * ----------------------------------------------------------------------
  * appnic_mii_read
  *
@@ -122,42 +90,14 @@ static void appnic_mdio_initialize(struct net_device *dev)
 
 static int appnic_mii_read(struct mii_bus *bus, int phy, int reg)
 {
-	struct appnic_device *pdata = (struct appnic_device *)bus->priv;
-	unsigned long flags;
 	unsigned short value;
-	unsigned long command = 0;
-	unsigned long status;
-
-	spin_lock_irqsave(&pdata->mdio_lock, flags);
 
-	/* Set the mdio_busy (status) bit. */
-	status = in_le32(MDIO_STATUS_RD_DATA);
-	status |= 0x40000000;
-	out_le32(MDIO_STATUS_RD_DATA, status);
+	/* Always returns success, so no need to check return status. */
+	acp_mdio_read(phy, reg, &value);
 
-	/* Write the command. */
-	command |= 0x10000000;          /* op_code: read */
-	command |= (phy & 0x1f) << 16;  /* port_addr (target device) */
-	command |= (reg & 0x1f) << 21;  /* device_addr (target register) */
-	out_le32(MDIO_CONTROL_RD_DATA, command);
-
-	/* Wait for the mdio_busy (status) bit to clear. */
-	do {
-		status = in_le32(MDIO_STATUS_RD_DATA);
-	} while (0 != (status & 0x40000000));
-
-	/* Wait for the mdio_busy (control) bit to clear. */
-	do {
-		command = in_le32(MDIO_CONTROL_RD_DATA);
-	} while (0 != (command & 0x80000000));
-
-	value = (unsigned short)(command & 0xffff);
-	spin_unlock_irqrestore(&pdata->mdio_lock, flags);
-
-	return value;
+	return (int)value;
 }
 
-
 /*
  * ----------------------------------------------------------------------
  * appnic_mii_write
@@ -165,43 +105,7 @@ static int appnic_mii_read(struct mii_bus *bus, int phy, int reg)
 
 static int appnic_mii_write(struct mii_bus *bus, int phy, int reg, u16 val)
 {
-	struct appnic_device *pdata = (struct appnic_device *)bus->priv;
-	unsigned long flags;
-	unsigned long command = 0;
-	unsigned long status;
-
-	spin_lock_irqsave(&pdata->mdio_lock, flags);
-
-	/* Wait for mdio_busy (control) to be clear. */
-	do {
-		command = in_le32(MDIO_CONTROL_RD_DATA);
-	} while (0 != (command & 0x80000000));
-
-	/* Set the mdio_busy (status) bit. */
-	status = in_le32(MDIO_STATUS_RD_DATA);
-	status |= 0x40000000;
-	out_le32(MDIO_STATUS_RD_DATA, status);
-
-	/* Write the command. */
-	command = 0x08000000;           /* op_code: write */
-	command |= (phy & 0x1f) << 16;  /* port_addr (target device) */
-	command |= (reg & 0x1f) << 21;  /* device_addr (target register) */
-	command |= (val & 0xffff);      /* value */
-	out_le32(MDIO_CONTROL_RD_DATA, command);
-
-	/* Wait for the mdio_busy (status) bit to clear. */
-	do {
-		status = in_le32(MDIO_STATUS_RD_DATA);
-	} while (0 != (status & 0x40000000));
-
-	/* Wait for the mdio_busy (control) bit to clear. */
-	do {
-		command = in_le32(MDIO_CONTROL_RD_DATA);
-	} while (0 != (command & 0x80000000));
-
-	spin_unlock_irqrestore(&pdata->mdio_lock, flags);
-
-	return 0;
+	return acp_mdio_write(phy, reg, val);
 }
 
 /*
@@ -1596,7 +1500,6 @@ int appnic_init(struct net_device *dev)
 	 * Initialize the spinlocks.
 	 */
 
-	spin_lock_init(&pdata->mdio_lock);
 	spin_lock_init(&pdata->dev_lock);
 	spin_lock_init(&pdata->extra_lock);
 
@@ -1807,15 +1710,6 @@ static int __devinit appnic_probe_config_dt(struct net_device *dev,
 	else
 		pdata->mdio_clock = field[0];
 
-	field = of_get_property(np, "mdio-reg", NULL);
-	if (!field) {
-		goto device_tree_failed;
-	} else {
-		value64 = of_translate_address(np, field);
-		value32 = field[1];
-		pdata->mdio_base = (unsigned long)ioremap(value64, value32);
-	}
-
 	field = of_get_property(np, "phy-address", NULL);
 	if (!field)
 		goto device_tree_failed;
@@ -1998,9 +1892,6 @@ static int __devinit appnic_drv_probe(struct platform_device *pdev)
 		goto out;
 	}
 
-	/* Initialize the MDIO interface. */
-	appnic_mdio_initialize(dev);
-
 	/* Initialize the PHY. */
 	rc = appnic_mii_init(pdev, dev);
 	if (rc) {
diff --git a/drivers/net/ethernet/lsi/lsi_acp_net.h b/drivers/net/ethernet/lsi/lsi_acp_net.h
index db4bfcf..f7de38d 100644
--- a/drivers/net/ethernet/lsi/lsi_acp_net.h
+++ b/drivers/net/ethernet/lsi/lsi_acp_net.h
@@ -93,7 +93,6 @@ struct appnic_device {
 	unsigned long dma_base;
 	unsigned long interrupt;
 	unsigned long mdio_clock;
-	unsigned long mdio_base;
 	unsigned long phy_address;
 	unsigned long ad_value;
 	unsigned char mac_addr[6];
@@ -149,7 +148,6 @@ struct appnic_device {
 	union appnic_queue_pointer tx_head;
 
 	/* Spin Lock */
-	spinlock_t mdio_lock;
 	spinlock_t dev_lock;
 	spinlock_t extra_lock;
 
-- 
1.8.3.4




More information about the linux-yocto mailing list