[linux-yocto] [PATCH 47/89] drivers/net/ethernet: combined arm and powerpc FEMAC ethernet driver
Paul Butler
butler.paul at gmail.com
Sun Oct 27 12:33:12 PDT 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