]> git.karo-electronics.de Git - linux-beck.git/commitdiff
stmmac: extend mac addr reg and fix perfect filering
authorGiuseppe CAVALLARO <peppe.cavallaro@st.com>
Sun, 13 May 2012 22:18:41 +0000 (22:18 +0000)
committerDavid S. Miller <davem@davemloft.net>
Mon, 14 May 2012 22:53:19 +0000 (18:53 -0400)
This patch is to extend the number of MAC address registers
for 16 to 32. In fact, other new 16 registers are available in new
chips and this can help on perfect filter mode for unicast.

This patch also fixes the perfect filtering mode by setting the
bit 31 in the MAC address registers.

v2: fixed Coding Style.

Signed-off-by: Gianni Antoniazzi <gianni.antoniazzi-ext@st.com>
Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/stmicro/stmmac/common.h
drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
drivers/net/ethernet/stmicro/stmmac/stmmac.h
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c

index f5dedcbf46518f1ab6d57dd77d992814bc520251..7164509e3832d9d6f48b0c2bfdff2d7d6acb291e 100644 (file)
@@ -280,7 +280,7 @@ struct stmmac_ops {
        /* Handle extra events on specific interrupts hw dependent */
        void (*host_irq_status) (void __iomem *ioaddr);
        /* Multicast filter setting */
-       void (*set_filter) (struct net_device *dev);
+       void (*set_filter) (struct net_device *dev, int id);
        /* Flow control setting */
        void (*flow_ctrl) (void __iomem *ioaddr, unsigned int duplex,
                           unsigned int fc, unsigned int pause_time);
index 54339a78e35891a818a65dfb24897db37ff18b28..1527f4ecd11acb67caca289263adf97da927dadd 100644 (file)
@@ -61,9 +61,11 @@ enum power_event {
 };
 
 /* GMAC HW ADDR regs */
-#define GMAC_ADDR_HIGH(reg)            (0x00000040+(reg * 8))
-#define GMAC_ADDR_LOW(reg)             (0x00000044+(reg * 8))
-#define GMAC_MAX_UNICAST_ADDRESSES     16
+#define GMAC_ADDR_HIGH(reg)    (((reg > 15) ? 0x00000800 : 0x00000040) + \
+                               (reg * 8))
+#define GMAC_ADDR_LOW(reg)     (((reg > 15) ? 0x00000804 : 0x00000044) + \
+                               (reg * 8))
+#define GMAC_MAX_PERFECT_ADDRESSES     32
 
 #define GMAC_AN_CTRL   0x000000c0      /* AN control */
 #define GMAC_AN_STATUS 0x000000c4      /* AN status */
@@ -205,4 +207,7 @@ enum rtc_control {
 #define GMAC_MMC_TX_INTR   0x108
 #define GMAC_MMC_RX_CSUM_OFFLOAD   0x208
 
+/* Synopsys Core versions */
+#define        DWMAC_CORE_3_40 34
+
 extern const struct stmmac_dma_ops dwmac1000_dma_ops;
index e7cbcd99c2cbd1a3f4688e54fc69aa16e1f89c28..b5e4d02f15c9a5a3089218973bdac3fa92f16cb4 100644 (file)
@@ -84,10 +84,11 @@ static void dwmac1000_get_umac_addr(void __iomem *ioaddr, unsigned char *addr,
                                GMAC_ADDR_LOW(reg_n));
 }
 
-static void dwmac1000_set_filter(struct net_device *dev)
+static void dwmac1000_set_filter(struct net_device *dev, int id)
 {
        void __iomem *ioaddr = (void __iomem *) dev->base_addr;
        unsigned int value = 0;
+       unsigned int perfect_addr_number;
 
        CHIP_DBG(KERN_INFO "%s: # mcasts %d, # unicast %d\n",
                 __func__, netdev_mc_count(dev), netdev_uc_count(dev));
@@ -121,8 +122,14 @@ static void dwmac1000_set_filter(struct net_device *dev)
                writel(mc_filter[1], ioaddr + GMAC_HASH_HIGH);
        }
 
+       /* Extra 16 regs are available in cores newer than the 3.40. */
+       if (id > DWMAC_CORE_3_40)
+               perfect_addr_number = GMAC_MAX_PERFECT_ADDRESSES;
+       else
+               perfect_addr_number = GMAC_MAX_PERFECT_ADDRESSES / 2;
+
        /* Handle multiple unicast addresses (perfect filtering)*/
-       if (netdev_uc_count(dev) > GMAC_MAX_UNICAST_ADDRESSES)
+       if (netdev_uc_count(dev) > perfect_addr_number)
                /* Switch to promiscuous mode is more than 16 addrs
                   are required */
                value |= GMAC_FRAME_FILTER_PR;
index efde50ff03f8691b66856ba05289ab5ff399c01e..19e0f4eed2bcf23fdec4a4ef21f079ad3856ce1c 100644 (file)
@@ -89,7 +89,7 @@ static void dwmac100_get_umac_addr(void __iomem *ioaddr, unsigned char *addr,
        stmmac_get_mac_addr(ioaddr, addr, MAC_ADDR_HIGH, MAC_ADDR_LOW);
 }
 
-static void dwmac100_set_filter(struct net_device *dev)
+static void dwmac100_set_filter(struct net_device *dev, int id)
 {
        void __iomem *ioaddr = (void __iomem *) dev->base_addr;
        u32 value = readl(ioaddr + MAC_CONTROL);
index f20aa12931d00a4a14ca87e6bf2f0493c4d5d536..4e0e18a44fcce7bc5a3c35c1eb1f560afb07d77d 100644 (file)
@@ -31,6 +31,8 @@
 #define DWMAC_LIB_DBG(fmt, args...)  do { } while (0)
 #endif
 
+#define GMAC_HI_REG_AE         0x80000000
+
 /* CSR1 enables the transmit DMA to check for new descriptor */
 void dwmac_enable_dma_transmission(void __iomem *ioaddr)
 {
@@ -233,7 +235,11 @@ void stmmac_set_mac_addr(void __iomem *ioaddr, u8 addr[6],
        unsigned long data;
 
        data = (addr[5] << 8) | addr[4];
-       writel(data, ioaddr + high);
+       /* For MAC Addr registers se have to set the Address Enable (AE)
+        * bit that has no effect on the High Reg 0 where the bit 31 (MO)
+        * is RO.
+        */
+       writel(data | GMAC_HI_REG_AE, ioaddr + high);
        data = (addr[3] << 24) | (addr[2] << 16) | (addr[1] << 8) | addr[0];
        writel(data, ioaddr + low);
 }
index db2de9a49952b588a7695268bbd1806437d34f9c..6b5d060ee9def7dd5fb5a8edac7037cc71bd869b 100644 (file)
@@ -85,6 +85,7 @@ struct stmmac_priv {
        struct clk *stmmac_clk;
 #endif
        int clk_csr;
+       int synopsys_id;
 };
 
 extern int phyaddr;
index 1a4cf8128f9170ea64ee1bf5b223543d1c070114..a9699ae49add535f95dfe9e1e1202c6c931bdebc 100644 (file)
@@ -1465,7 +1465,7 @@ static void stmmac_set_rx_mode(struct net_device *dev)
        struct stmmac_priv *priv = netdev_priv(dev);
 
        spin_lock(&priv->lock);
-       priv->hw->mac->set_filter(dev);
+       priv->hw->mac->set_filter(dev, priv->synopsys_id);
        spin_unlock(&priv->lock);
 }
 
@@ -1806,7 +1806,7 @@ static int stmmac_hw_init(struct stmmac_priv *priv)
        priv->hw->ring = &ring_mode_ops;
 
        /* Get and dump the chip ID */
-       stmmac_get_synopsys_id(priv);
+       priv->synopsys_id = stmmac_get_synopsys_id(priv);
 
        /* Get the HW capability (new GMAC newer than 3.50a) */
        priv->hw_cap_support = stmmac_get_hw_features(priv);