[linux-yocto] [PATCH 54/94] drivers/net/ethernet: combined arm and powerpc FEMAC ethernet driver

Paul Butler butler.paul at gmail.com
Thu Nov 7 17:13:08 PST 2013


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

Finalized changes and integration test with both elpaso and amarillo
boards.

Signed-off-by: David Mercado <david.mercado at windriver.com>
---
 arch/powerpc/sysdev/Makefile           |   2 +-
 arch/powerpc/sysdev/lsi_acp_wrappers.c | 274 ---------------------------------
 drivers/net/ethernet/lsi/lsi_acp_net.c |  73 +++++----
 drivers/net/ethernet/lsi/lsi_acp_net.h |   6 +-
 4 files changed, 45 insertions(+), 310 deletions(-)
 delete mode 100644 arch/powerpc/sysdev/lsi_acp_wrappers.c

diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index a95b59f..6354d1c 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 lsi_acp_wrappers.o
+obj-$(CONFIG_ACP)		+= lsi_acp_ncr.o
diff --git a/arch/powerpc/sysdev/lsi_acp_wrappers.c b/arch/powerpc/sysdev/lsi_acp_wrappers.c
deleted file mode 100644
index f944741..0000000
--- a/arch/powerpc/sysdev/lsi_acp_wrappers.c
+++ /dev/null
@@ -1,274 +0,0 @@
-/*
- * 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/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");
-
-/*
-  ==============================================================================
-  ==============================================================================
-  Platform Device Registration
-  ==============================================================================
-  ==============================================================================
-*/
-
-/*
-  ------------------------------------------------------------------------------
-  acp_platform_device_register
-*/
-
-int
-acp_platform_device_register(struct platform_device *pdev)
-{
-	return platform_device_register(pdev);
-}
-
-EXPORT_SYMBOL(acp_platform_device_register);
-
-/*
-  ------------------------------------------------------------------------------
-  acp_platform_device_unregister
-*/
-
-void
-acp_platform_device_unregister(struct platform_device *pdev)
-{
-	platform_device_unregister(pdev);
-
-	return;
-}
-
-EXPORT_SYMBOL(acp_platform_device_unregister);
-
-/*
-  ============================================================================
-  ============================================================================
-  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);
-
-/*
- * -------------------------------------------------------------------------
- * 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 cfd8106..d5204f1 100644
--- a/drivers/net/ethernet/lsi/lsi_acp_net.c
+++ b/drivers/net/ethernet/lsi/lsi_acp_net.c
@@ -27,15 +27,33 @@
  *
  *    ethaddr - MAC address of interface, in xx:xx:xx:xx:xx:xx format
  *
- *    ad_value - PHY advertise value. Can be set to one of these or multiple
- *               can be OR'ed together. If not set, the driver defaults to
- *               the OR'ed quantity of all four (0x1e1).
+ *    phy-addr - Specific address of PHY (0 - 0x20). If not specified,
+ *               the driver will scan the bus and will attach to the first
+ *               PHY it finds.
+ *
+ *    ad-value - PHY advertise value. Can be set to one of these or they
+ *               be OR'ed together. If not set, the driver sets the
+ *               advertised value equal to what the driver supports.
  *
  *               0x101 - 100/Full
  *               0x81  - 100/Half
  *               0x41  - 10/Full
  *               0x21  - 10/Half
  *
+ * 3) This driver allows the option to disable auto negotiation and manually
+ *    specify the speed and duplex setting, with the use of the device tree
+ *    variable "phy-link". Legal values for this variable are:
+ *
+ *    "auto"  - auto negotiation enabled
+ *    "100MF" - auto negotation disabled, set to 100MB Full Duplex
+ *    "10MH"  - auto negotation disabled, set to 100MB Half Duplex
+ *    "10MF"  - auto negotation disabled, set to 10MB Full Duplex
+ *    "10MH"  - auto negotation disabled, set to 10MB Half Duplex
+ *
+ *    NOTE: If the phy-link variable is not present in the device tree, or
+ *    if an invalid value is used, the driver defaults to auto negotiation
+ *    mode.
+ *
  */
 
 #include <linux/module.h>
@@ -72,8 +90,8 @@
 #include <asm/lsi/acp_ncr.h>
 #include "lsi_acp_net.h"
 
+/* Define to disable full duplex mode on Amarillo boards */
 #undef AMARILLO_WA
-/*#define AMARILLO_WA*/
 
 #define LSI_DRV_NAME           "acp-femac"
 #define LSI_MDIO_NAME          "acp-femac-mdio"
@@ -152,11 +170,12 @@ static void appnic_handle_link_change(struct net_device *dev)
 	if (phydev->link) {
 		if ((pdata->speed != phydev->speed) ||
 		    (pdata->duplex != phydev->duplex)) {
-
+#ifndef AMARILLO_WA
 			if (phydev->duplex) {
 				rx_configuration |= APPNIC_RX_CONF_DUPLEX;
 				tx_configuration |= APPNIC_TX_CONF_DUPLEX;
 			}
+#endif
 			if (phydev->speed == SPEED_100) {
 				rx_configuration |= APPNIC_RX_CONF_SPEED;
 				tx_configuration |= APPNIC_TX_CONF_SPEED;
@@ -181,11 +200,6 @@ static void appnic_handle_link_change(struct net_device *dev)
 		status_change = 1;
 	}
 
-#ifdef AMARILLO_WA
-	rx_configuration &= ~0x1000;
-	tx_configuration &= ~0x1000;
-#endif
-
 	if (status_change) {
 		if (phydev->link) {
 			netif_carrier_on(dev);
@@ -236,10 +250,11 @@ static int appnic_mii_probe(struct net_device *dev)
 skip_first:
 
 	/*
-	 * For the Axxia AXM, allow the option to disable auto
-	 * negotiation and manually specify the speed and duplex
-	 * setting with the use of a environment setting.
+	 * Allow the option to disable auto negotiation and manually specify
+	 * the link speed and duplex setting with the use of a environment
+	 * setting.
 	 */
+
 	if (0 == pdata->phy_link_auto) {
 		phydev->autoneg = AUTONEG_DISABLE;
 		phydev->speed =
@@ -279,14 +294,16 @@ skip_first:
 		rc = acp_mdio_write(phydev->addr, PHY_BCM_TEST_REG, val);
 	}
 #endif
-
 	netdev_info(dev,
 		    "attached PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)\n",
 		    phydev->drv->name, dev_name(&phydev->dev), phydev->irq);
 
 	/* Mask with MAC supported features */
 	phydev->supported &= PHY_BASIC_FEATURES;
-	phydev->advertising = mii_adv_to_ethtool_adv_t(pdata->ad_value);
+	if (pdata->ad_value)
+		phydev->advertising = mii_adv_to_ethtool_adv_t(pdata->ad_value);
+	else
+		phydev->advertising = phydev->supported;
 
 	pdata->link = 0;
 	pdata->speed = 0;
@@ -745,12 +762,10 @@ static void lsinet_rx_packet(struct net_device *dev)
 		return;
 	}
 
-#if 0 /* DAVE - why is this commented out? */
 	ok_stat = read_mac(APPNIC_RX_STAT_PACKET_OK);
 	overflow_stat = read_mac(APPNIC_RX_STAT_OVERFLOW);
 	crc_stat = read_mac(APPNIC_RX_STAT_CRC_ERROR);
 	align_stat = read_mac(APPNIC_RX_STAT_ALIGN_ERROR);
-#endif
 
 	/*
 	 * Copy the received packet into the skb.
@@ -1121,7 +1136,6 @@ static int appnic_hard_start_xmit(struct sk_buff *skb,
 	length = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len;
 	buf_per_desc = pdata->tx_buf_sz / pdata->tx_num_desc;
 
-	/* dump_registers(dev); */
 	/*
 	 * If enough transmit descriptors are available, copy and transmit.
 	 */
@@ -1432,10 +1446,10 @@ int appnic_init(struct net_device *dev)
 				   &pdata->dma_alloc_dma,
 				   GFP_KERNEL);
 #else
-	device->dev.archdata.dma_ops = &dma_direct_ops;
+	dev->dev.archdata.dma_ops = &dma_direct_ops;
 
 	pdata->dma_alloc = (void *)
-		dma_alloc_coherent(&device->dev,
+		dma_alloc_coherent(&dev->dev,
 				   pdata->dma_alloc_size,
 				   &pdata->dma_alloc_dma,
 				   GFP_KERNEL);
@@ -1762,13 +1776,12 @@ static int __devinit appnic_probe_config_dt(struct net_device *dev,
 {
 	struct appnic_device *pdata = netdev_priv(dev);
 	const u32 *field;
+	const char *macspeed;
+	int length;
 #ifndef CONFIG_ARM
 	u64 value64;
 	u32 value32;
-#else
-	const char *macspeed;
 #endif
-	int length;
 
 	if (!np)
 		return -ENODEV;
@@ -1848,7 +1861,6 @@ static int __devinit appnic_probe_config_dt(struct net_device *dev,
 		pdata->ad_value = field[0];
 #endif
 
-#ifdef CONFIG_ARM
 	macspeed = of_get_property(np, "phy-link", NULL);
 
 	if (macspeed) {
@@ -1870,12 +1882,15 @@ static int __devinit appnic_probe_config_dt(struct net_device *dev,
 			pdata->phy_link_auto = 0;
 			pdata->phy_link_speed = 0;
 			pdata->phy_link_duplex = 0;
+		} else {
+			pr_err("Invalid phy-link value \"%s\" in DTS. Defaulting to \"auto\".\n",
+			       macspeed);
+			pdata->phy_link_auto = 1;
 		}
 	} else {
 		/* Auto is the default. */
 		pdata->phy_link_auto = 1;
 	}
-#endif
 
 	field = of_get_property(np, "mac-address", &length);
 	if (!field || 6 != length) {
@@ -1995,7 +2010,7 @@ static int __devinit appnic_drv_probe(struct platform_device *pdev)
 			dma_base = ioremap(0x002000482000ULL, 0x1000);
 			pdata->dma_base =
 			 (unsigned long)ioremap(0x002000482000ULL, 0x1000);
-			pdata->interrupt = 33;
+			pdata->dma_interrupt = 33;
 		}
 #else
 		/* Neither dtb info nor ubootenv driver found. */
@@ -2024,12 +2039,6 @@ static int __devinit appnic_drv_probe(struct platform_device *pdev)
 	}
 
 #endif
-	/* ad_value should never be 0. */
-	if (pdata->ad_value == 0) {
-		pdata->ad_value = 0x1e1;
-		pr_err("%s: Set ad_value to default of 0x%lx\n",
-		       LSI_DRV_NAME, pdata->ad_value);
-	}
 
 	/* Initialize the device. */
 	rc = appnic_init(dev);
diff --git a/drivers/net/ethernet/lsi/lsi_acp_net.h b/drivers/net/ethernet/lsi/lsi_acp_net.h
index 9289073..7b6f2b3 100644
--- a/drivers/net/ethernet/lsi/lsi_acp_net.h
+++ b/drivers/net/ethernet/lsi/lsi_acp_net.h
@@ -86,7 +86,7 @@ struct appnic_dma_descriptor {
 	unsigned long host_data_memory_pointer;
 #endif
 
-} __attribute__ ((packed));
+} __packed;
 
 union appnic_queue_pointer {
 
@@ -102,9 +102,9 @@ union appnic_queue_pointer {
 		unsigned long generation_bit:1;
 		unsigned long offset:20;
 #endif
-	} __attribute__ ((packed)) bits;
+	} __packed bits;
 
-} __attribute__ ((packed));
+} __packed;
 
 /*
   =============================================================================
-- 
1.8.3.4




More information about the linux-yocto mailing list