The driver takes phy address as a parameter but ignores it, and instead
takes the first available phy in the address range.  This patch allows
one to select a specific phy on boards that have multiple phys.
Support for the new BCM 5221 phy - acp_net

Signed-off-by: Paul Butler <paul.but...@windriver.com>
Signed-off-by: David Mercado <david.merc...@windriver.com>
Signed-off-by: John Jacques <john.jacq...@lsi.com>
---
 drivers/net/ethernet/lsi/lsi_acp_net.c | 207 ++++++++++++++++++++++++++++-----
 1 file changed, 181 insertions(+), 26 deletions(-)

diff --git a/drivers/net/ethernet/lsi/lsi_acp_net.c 
b/drivers/net/ethernet/lsi/lsi_acp_net.c
index 605a431..331c8e4 100644
--- a/drivers/net/ethernet/lsi/lsi_acp_net.c
+++ b/drivers/net/ethernet/lsi/lsi_acp_net.c
@@ -20,7 +20,9 @@
  *
  * NOTES:
  *
- * 1) This driver parses the DTB for driver specific settings. A few of
+ * 1) This driver is used by both ACP (PPC) and AXM (ARM) platforms.
+ *
+ * 2) This driver parses the DTB for driver specific settings. A few of
  *    them can be overriden by setting environment variables in U-boot:
  *
  *    ethaddr - MAC address of interface, in xx:xx:xx:xx:xx:xx format
@@ -59,6 +61,8 @@
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 #include <linux/dma-mapping.h>
 
 #include <linux/uaccess.h>
@@ -68,9 +72,12 @@
 #include <asm/lsi/acp_ncr.h>
 #include "lsi_acp_net.h"
 
+#undef AMARILLO_WA
+/*#define AMARILLO_WA*/
+
 #define LSI_DRV_NAME           "acp-femac"
 #define LSI_MDIO_NAME          "acp-femac-mdio"
-#define LSI_DRV_VERSION        "2013-04-30"
+#define LSI_DRV_VERSION        "2013-09-10"
 
 MODULE_AUTHOR("John Jacques");
 MODULE_DESCRIPTION("LSI ACP-FEMAC Ethernet driver");
@@ -81,6 +88,10 @@ static void *rx_base;
 static void *tx_base;
 static void *dma_base;
 
+/* BCM5221 registers */
+#define PHY_BCM_TEST_REG       0x1f
+#define PHY_AUXILIARY_MODE3    0x1d
+
 /*
  * ----------------------------------------------------------------------
  * appnic_mii_read
@@ -124,9 +135,13 @@ static void appnic_handle_link_change(struct net_device 
*dev)
        unsigned long tx_configuration = 0;
 
        rx_configuration =
+#ifdef CONFIG_ARM
+               APPNIC_RX_CONF_STRIPCRC;
+#else
                (APPNIC_RX_CONF_STRIPCRC |
                 APPNIC_RX_CONF_RXFCE |
                 APPNIC_RX_CONF_TXFCE);
+#endif
        tx_configuration =
                (APPNIC_TX_CONF_ENABLE_SWAP_SA |
                 APPNIC_TX_CONF_APP_CRC_ENABLE |
@@ -178,6 +193,11 @@ static void appnic_handle_link_change(struct net_device 
*dev)
                        netdev_info(dev, "link down\n");
                }
 
+#ifdef AMARILLO_WA
+               rx_configuration &= ~0x1000;
+               tx_configuration &= ~0x1000;
+#endif
+
                if (rx_configuration != read_mac(APPNIC_RX_CONF))
                        write_mac(rx_configuration, APPNIC_RX_CONF);
 
@@ -199,13 +219,35 @@ static int appnic_mii_probe(struct net_device *dev)
        struct phy_device *phydev = NULL;
        int ret;
 
+       if (pdata->phy_address && (pdata->phy_address < PHY_MAX_ADDR)) {
+               phydev = pdata->mii_bus->phy_map[pdata->phy_address];
+               if (phydev)
+                       goto skip_first;
+       }
+
        /* Find the first phy */
        phydev = phy_find_first(pdata->mii_bus);
        if (!phydev) {
+               pr_crit("!!! no PHY found !!!\n");
                netdev_err(dev, " no PHY found\n");
                return -ENODEV;
        }
 
+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.
+        */
+       if (0 == pdata->phy_link_auto) {
+               phydev->autoneg = AUTONEG_DISABLE;
+               phydev->speed =
+                       0 == pdata->phy_link_speed ? SPEED_10 : SPEED_100;
+               phydev->duplex =
+                       0 == pdata->phy_link_duplex ? DUPLEX_HALF : DUPLEX_FULL;
+       }
+
        ret = phy_connect_direct(dev, phydev,
                                 &appnic_handle_link_change, 0,
                                 PHY_INTERFACE_MODE_MII);
@@ -215,6 +257,29 @@ static int appnic_mii_probe(struct net_device *dev)
                return ret;
        }
 
+#ifdef CONFIG_ARCH_AXXIA
+       /*
+        * For the Axxia AXM, set RX FIFO size to 0x7.
+        */
+       {
+               u16 val;
+               int rc;
+
+               /* Enable access to shadow register @ 0x1d */
+               rc = acp_mdio_read(phydev->addr, PHY_BCM_TEST_REG, &val);
+               val |= 0x80;
+               rc = acp_mdio_write(phydev->addr, PHY_BCM_TEST_REG, val);
+
+               /* Set RX FIFO size to 0x7 */
+               rc = acp_mdio_write(phydev->addr, PHY_AUXILIARY_MODE3, 0x7);
+
+               /* Disable access to shadow register @ 0x1d */
+               rc = acp_mdio_read(phydev->addr, PHY_BCM_TEST_REG, &val);
+               val &= ~0x80;
+               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);
@@ -663,7 +728,8 @@ static void lsinet_rx_packet(struct net_device *dev)
        struct sk_buff *sk_buff;
        unsigned bytes_copied = 0;
        unsigned error_num = 0;
-       unsigned long ok_stat, overflow_stat, crc_stat, align_stat;
+       unsigned long ok_stat = 0, overflow_stat = 0;
+       unsigned long crc_stat = 0, align_stat = 0;
 
        spin_lock(&pdata->extra_lock);
 
@@ -679,10 +745,12 @@ 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.
@@ -1053,6 +1121,7 @@ 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.
         */
@@ -1118,6 +1187,10 @@ static int appnic_hard_start_xmit(struct sk_buff *skb,
                        descriptor.start_of_packet = 0;
                }
 
+#ifdef CONFIG_ARM
+               /* ARM Data sync barrier */
+               asm volatile ("mcr p15,0,%0,c7,c10,4" : : "r" (0));
+#endif
                write_mac(pdata->tx_head.raw, APPNIC_DMA_TX_HEAD_POINTER);
                dev->trans_start = jiffies;
        } else {
@@ -1347,21 +1420,29 @@ int appnic_init(struct net_device *dev)
                /* The TX buffer (and padding...) */
                (pdata->tx_buf_sz) + (BUFFER_ALIGNMENT);
 
-
        /*
         * This needs to be set to something sane for
         * dma_alloc_coherent()
         */
 
-       dev->dev.archdata.dma_ops = &dma_direct_ops;
+#if defined(CONFIG_ARM)
+       pdata->dma_alloc = (void *)
+               dma_alloc_coherent(NULL,
+                                  pdata->dma_alloc_size,
+                                  &pdata->dma_alloc_dma,
+                                  GFP_KERNEL);
+#else
+       device->dev.archdata.dma_ops = &dma_direct_ops;
 
-       pdata->dma_alloc = (void *)dma_alloc_coherent(&dev->dev,
-                                                   pdata->dma_alloc_size,
-                                                   &pdata->dma_alloc_dma,
-                                                   GFP_KERNEL);
+       pdata->dma_alloc = (void *)
+               dma_alloc_coherent(&device->dev,
+                                  pdata->dma_alloc_size,
+                                  &pdata->dma_alloc_dma,
+                                  GFP_KERNEL);
+#endif
 
        if ((void *)0 == pdata->dma_alloc) {
-               pr_err("%s: Could not allocate %d bytes of DMA-able memory!\n",
+               pr_err("%s: Can't allocate %d bytes of DMA-able memory!\n",
                       LSI_DRV_NAME, pdata->dma_alloc_size);
                kfree(pdata);
                return -ENOMEM;
@@ -1370,13 +1451,17 @@ int appnic_init(struct net_device *dev)
        pdata->dma_alloc_offset = (int)pdata->dma_alloc -
                                        (int)pdata->dma_alloc_dma;
 
+#ifdef CONFIG_ARM
+       pdata->dma_alloc_rx = (void *)dma_alloc_coherent(NULL,
+#else
        pdata->dma_alloc_rx = (void *)dma_alloc_coherent(&dev->dev,
+#endif
                                                    pdata->dma_alloc_size_rx,
                                                    &pdata->dma_alloc_dma_rx,
                                                    GFP_KERNEL);
 
        if ((void *)0 == pdata->dma_alloc_rx) {
-               pr_err("%s: Could not allocate %d bytes of DMA-able memory!\n",
+               pr_err("%s: Can't allocate %d bytes of RX DMA-able memory!\n",
                       LSI_DRV_NAME, pdata->dma_alloc_size_rx);
                dma_free_coherent(&dev->dev, pdata->dma_alloc_size,
                                  pdata->dma_alloc, pdata->dma_alloc_dma);
@@ -1387,13 +1472,17 @@ int appnic_init(struct net_device *dev)
        pdata->dma_alloc_offset_rx = (int)pdata->dma_alloc_rx -
                                        (int)pdata->dma_alloc_dma_rx;
 
+#ifdef CONFIG_ARM
+       pdata->dma_alloc_tx = (void *)dma_alloc_coherent(NULL,
+#else
        pdata->dma_alloc_tx = (void *)dma_alloc_coherent(&dev->dev,
+#endif
                                                    pdata->dma_alloc_size_tx,
                                                    &pdata->dma_alloc_dma_tx,
                                                    GFP_KERNEL);
 
        if ((void *)0 == pdata->dma_alloc_tx) {
-               pr_err("%s: Could not allocate %d bytes of DMA-able memory!\n",
+               pr_err("%s: Can't allocate %d bytes of TX DMA-able memory!\n",
                       LSI_DRV_NAME, pdata->dma_alloc_size_tx);
                dma_free_coherent(&dev->dev, pdata->dma_alloc_size,
                                  pdata->dma_alloc, pdata->dma_alloc_dma);
@@ -1414,16 +1503,16 @@ int appnic_init(struct net_device *dev)
 
        pdata->rx_tail = (union appnic_queue_pointer *)dma_offset;
        pdata->rx_tail_dma = (int)pdata->rx_tail - (int)pdata->dma_alloc_offset;
+       dma_offset += sizeof(union appnic_queue_pointer);
        memset((void *)pdata->rx_tail, 0,
               sizeof(union appnic_queue_pointer));
 
-       dma_offset += sizeof(union appnic_queue_pointer);
 
        pdata->tx_tail = (union appnic_queue_pointer *)dma_offset;
        pdata->tx_tail_dma = (int)pdata->tx_tail - (int)pdata->dma_alloc_offset;
+       dma_offset += sizeof(union appnic_queue_pointer);
        memset((void *)pdata->tx_tail, 0, sizeof(union appnic_queue_pointer));
 
-       dma_offset += sizeof(union appnic_queue_pointer);
 
        /*
         * Initialize the descriptor pointers
@@ -1431,14 +1520,15 @@ int appnic_init(struct net_device *dev)
 
        pdata->rx_desc = (struct appnic_dma_descriptor *)ALIGN64B(dma_offset);
        pdata->rx_desc_dma = (int)pdata->rx_desc - (int)pdata->dma_alloc_offset;
-       memset((void *)pdata->rx_desc, 0,
-              (sizeof(struct appnic_dma_descriptor) * pdata->rx_num_desc));
-
        dma_offset += (sizeof(struct appnic_dma_descriptor) *
                        pdata->rx_num_desc) + (DESCRIPTOR_GRANULARITY);
+       memset((void *)pdata->rx_desc, 0,
+              (sizeof(struct appnic_dma_descriptor) * pdata->rx_num_desc));
 
        pdata->tx_desc = (struct appnic_dma_descriptor *)ALIGN64B(dma_offset);
        pdata->tx_desc_dma = (int)pdata->tx_desc - (int)pdata->dma_alloc_offset;
+       dma_offset += (sizeof(struct appnic_dma_descriptor) *
+                       pdata->tx_num_desc) + (DESCRIPTOR_GRANULARITY);
        memset((void *)pdata->tx_desc, 0,
               (sizeof(struct appnic_dma_descriptor) * pdata->tx_num_desc));
 
@@ -1511,10 +1601,7 @@ int appnic_init(struct net_device *dev)
        write_mac(0x1, APPNIC_RX_MODE);
        write_mac(0x0, APPNIC_TX_SOFT_RESET);
        write_mac(0x1, APPNIC_TX_MODE);
-       if (is_asic())
-               write_mac(0x300a, APPNIC_TX_WATERMARK);
-       else
-               write_mac(0xc00096, APPNIC_TX_WATERMARK);
+       write_mac(0x300a, APPNIC_TX_WATERMARK);
        write_mac(0x1, APPNIC_TX_HALF_DUPLEX_CONF);
        write_mac(0xffff, APPNIC_TX_TIME_VALUE_CONF);
        write_mac(0x1, APPNIC_TX_INTERRUPT_CONTROL);
@@ -1523,12 +1610,20 @@ int appnic_init(struct net_device *dev)
        write_mac(0x1, APPNIC_RX_EXTERNAL_INTERRUPT_CONTROL);
        write_mac(0x40010000, APPNIC_DMA_PCI_CONTROL);
        write_mac(0x30000, APPNIC_DMA_CONTROL);
+#ifdef CONFIG_ARM
+       writel(0x280044, dma_base + 0x60);
+       writel(0xc0, dma_base + 0x64);
+#else
        out_le32(dma_base + 0x60, 0x280044);
        out_le32(dma_base + 0x64, 0xc0);
+#endif
 
        /*
         * Set the MAC address
         */
+       pr_info("%s: MAC %02x:%02x:%02x:%02x:%02x:%02x\n", LSI_DRV_NAME,
+               dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
+               dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
 
        memcpy(&(address.sa_data[0]), dev->dev_addr, 6);
        appnic_set_mac_address(dev, &address);
@@ -1612,7 +1707,10 @@ int appnic_init(struct net_device *dev)
        /* Fill in the net_device structure */
 
        ether_setup(dev);
-       dev->irq = irq_create_mapping(NULL, pdata->interrupt);
+#ifdef CONFIG_ARM
+       dev->irq = pdata->dma_interrupt;
+#else
+       dev->irq = irq_create_mapping(NULL, pdata->dma_interrupt);
        if (NO_IRQ == dev->irq) {
                pr_err("%s: irq_create_mapping() failed\n", LSI_DRV_NAME);
                return -EBUSY;
@@ -1622,6 +1720,7 @@ int appnic_init(struct net_device *dev)
                pr_err("%s: set_irq_type() failed\n", LSI_DRV_NAME);
                return -EBUSY;
        }
+#endif
 
        dev->netdev_ops = &appnic_netdev_ops;
 
@@ -1663,13 +1762,22 @@ static int __devinit appnic_probe_config_dt(struct 
net_device *dev,
 {
        struct appnic_device *pdata = netdev_priv(dev);
        const u32 *field;
+#ifndef CONFIG_ARM
        u64 value64;
        u32 value32;
+#else
+       const char *macspeed;
+#endif
        int length;
 
        if (!np)
                return -ENODEV;
 
+#ifdef CONFIG_ARM
+       rx_base = of_iomap(np, 0);
+       tx_base = of_iomap(np, 1);
+       dma_base = of_iomap(np, 2);
+#else
        field = of_get_property(np, "enabled", NULL);
 
        if (!field || (field && (0 == *field)))
@@ -1686,41 +1794,88 @@ static int __devinit appnic_probe_config_dt(struct 
net_device *dev,
        value32 = field[1];
        field += 2;
        rx_base = ioremap(value64, value32);
-       pdata->rx_base = (unsigned long)rx_base;
        value64 = of_translate_address(np, field);
        value32 = field[1];
        field += 2;
        tx_base = ioremap(value64, value32);
-       pdata->tx_base = (unsigned long)tx_base;
        value64 = of_translate_address(np, field);
        value32 = field[1];
        field += 2;
        dma_base = ioremap(value64, value32);
+#endif
+       pdata->rx_base = (unsigned long)rx_base;
+       pdata->tx_base = (unsigned long)tx_base;
        pdata->dma_base = (unsigned long)dma_base;
 
+#ifdef CONFIG_ARM
+       pdata->tx_interrupt = irq_of_parse_and_map(np, 0);
+       pdata->rx_interrupt = irq_of_parse_and_map(np, 1);
+       pdata->dma_interrupt = irq_of_parse_and_map(np, 2);
+#else
        field = of_get_property(np, "interrupts", NULL);
        if (!field)
                goto device_tree_failed;
        else
-               pdata->interrupt = field[0];
-
+               pdata->dma_interrupt = field[0];
+#endif
        field = of_get_property(np, "mdio-clock", NULL);
        if (!field)
                goto device_tree_failed;
        else
+#ifdef CONFIG_ARM
+               pdata->mdio_clock = swab32(field[0]);
+#else
                pdata->mdio_clock = field[0];
+#endif
 
        field = of_get_property(np, "phy-address", NULL);
        if (!field)
                goto device_tree_failed;
        else
+#ifdef CONFIG_ARM
+               pdata->phy_address = swab32(field[0]);
+#else
                pdata->phy_address = field[0];
+#endif
 
        field = of_get_property(np, "ad-value", NULL);
        if (!field)
                goto device_tree_failed;
        else
+#ifdef CONFIG_ARM
+               pdata->ad_value = swab32(field[0]);
+#else
                pdata->ad_value = field[0];
+#endif
+
+#ifdef CONFIG_ARM
+       macspeed = of_get_property(np, "phy-link", NULL);
+
+       if (macspeed) {
+               if (0 == strncmp(macspeed, "auto", strlen("auto"))) {
+                       pdata->phy_link_auto = 1;
+               } else if (0 == strncmp(macspeed, "100MF", strlen("100MF"))) {
+                       pdata->phy_link_auto = 0;
+                       pdata->phy_link_speed = 1;
+                       pdata->phy_link_duplex = 1;
+               } else if (0 == strncmp(macspeed, "100MH", strlen("100MH"))) {
+                       pdata->phy_link_auto = 0;
+                       pdata->phy_link_speed = 1;
+                       pdata->phy_link_duplex = 0;
+               } else if (0 == strncmp(macspeed, "10MF", strlen("10MF"))) {
+                       pdata->phy_link_auto = 0;
+                       pdata->phy_link_speed = 0;
+                       pdata->phy_link_duplex = 1;
+               } else if (0 == strncmp(macspeed, "10MH", strlen("10MH"))) {
+                       pdata->phy_link_auto = 0;
+                       pdata->phy_link_speed = 0;
+                       pdata->phy_link_duplex = 0;
+               }
+       } else {
+               /* Auto is the default. */
+               pdata->phy_link_auto = 1;
+       }
+#endif
 
        field = of_get_property(np, "mac-address", &length);
        if (!field || 6 != length) {
-- 
1.8.3.4

_______________________________________________
linux-yocto mailing list
linux-yocto@yoctoproject.org
https://lists.yoctoproject.org/listinfo/linux-yocto

Reply via email to