Commit cffb13f4 authored by Giuseppe CAVALLARO's avatar Giuseppe CAVALLARO Committed by David S. Miller

stmmac: extend mac addr reg and fix perfect filering

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: default avatarGianni Antoniazzi <gianni.antoniazzi-ext@st.com>
Signed-off-by: default avatarGiuseppe Cavallaro <peppe.cavallaro@st.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 20fb18da
...@@ -280,7 +280,7 @@ struct stmmac_ops { ...@@ -280,7 +280,7 @@ struct stmmac_ops {
/* Handle extra events on specific interrupts hw dependent */ /* Handle extra events on specific interrupts hw dependent */
void (*host_irq_status) (void __iomem *ioaddr); void (*host_irq_status) (void __iomem *ioaddr);
/* Multicast filter setting */ /* Multicast filter setting */
void (*set_filter) (struct net_device *dev); void (*set_filter) (struct net_device *dev, int id);
/* Flow control setting */ /* Flow control setting */
void (*flow_ctrl) (void __iomem *ioaddr, unsigned int duplex, void (*flow_ctrl) (void __iomem *ioaddr, unsigned int duplex,
unsigned int fc, unsigned int pause_time); unsigned int fc, unsigned int pause_time);
......
...@@ -61,9 +61,11 @@ enum power_event { ...@@ -61,9 +61,11 @@ enum power_event {
}; };
/* GMAC HW ADDR regs */ /* GMAC HW ADDR regs */
#define GMAC_ADDR_HIGH(reg) (0x00000040+(reg * 8)) #define GMAC_ADDR_HIGH(reg) (((reg > 15) ? 0x00000800 : 0x00000040) + \
#define GMAC_ADDR_LOW(reg) (0x00000044+(reg * 8)) (reg * 8))
#define GMAC_MAX_UNICAST_ADDRESSES 16 #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_CTRL 0x000000c0 /* AN control */
#define GMAC_AN_STATUS 0x000000c4 /* AN status */ #define GMAC_AN_STATUS 0x000000c4 /* AN status */
...@@ -205,4 +207,7 @@ enum rtc_control { ...@@ -205,4 +207,7 @@ enum rtc_control {
#define GMAC_MMC_TX_INTR 0x108 #define GMAC_MMC_TX_INTR 0x108
#define GMAC_MMC_RX_CSUM_OFFLOAD 0x208 #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; extern const struct stmmac_dma_ops dwmac1000_dma_ops;
...@@ -84,10 +84,11 @@ static void dwmac1000_get_umac_addr(void __iomem *ioaddr, unsigned char *addr, ...@@ -84,10 +84,11 @@ static void dwmac1000_get_umac_addr(void __iomem *ioaddr, unsigned char *addr,
GMAC_ADDR_LOW(reg_n)); 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; void __iomem *ioaddr = (void __iomem *) dev->base_addr;
unsigned int value = 0; unsigned int value = 0;
unsigned int perfect_addr_number;
CHIP_DBG(KERN_INFO "%s: # mcasts %d, # unicast %d\n", CHIP_DBG(KERN_INFO "%s: # mcasts %d, # unicast %d\n",
__func__, netdev_mc_count(dev), netdev_uc_count(dev)); __func__, netdev_mc_count(dev), netdev_uc_count(dev));
...@@ -121,8 +122,14 @@ static void dwmac1000_set_filter(struct net_device *dev) ...@@ -121,8 +122,14 @@ static void dwmac1000_set_filter(struct net_device *dev)
writel(mc_filter[1], ioaddr + GMAC_HASH_HIGH); 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)*/ /* 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 /* Switch to promiscuous mode is more than 16 addrs
are required */ are required */
value |= GMAC_FRAME_FILTER_PR; value |= GMAC_FRAME_FILTER_PR;
......
...@@ -89,7 +89,7 @@ static void dwmac100_get_umac_addr(void __iomem *ioaddr, unsigned char *addr, ...@@ -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); 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; void __iomem *ioaddr = (void __iomem *) dev->base_addr;
u32 value = readl(ioaddr + MAC_CONTROL); u32 value = readl(ioaddr + MAC_CONTROL);
......
...@@ -31,6 +31,8 @@ ...@@ -31,6 +31,8 @@
#define DWMAC_LIB_DBG(fmt, args...) do { } while (0) #define DWMAC_LIB_DBG(fmt, args...) do { } while (0)
#endif #endif
#define GMAC_HI_REG_AE 0x80000000
/* CSR1 enables the transmit DMA to check for new descriptor */ /* CSR1 enables the transmit DMA to check for new descriptor */
void dwmac_enable_dma_transmission(void __iomem *ioaddr) void dwmac_enable_dma_transmission(void __iomem *ioaddr)
{ {
...@@ -233,7 +235,11 @@ void stmmac_set_mac_addr(void __iomem *ioaddr, u8 addr[6], ...@@ -233,7 +235,11 @@ void stmmac_set_mac_addr(void __iomem *ioaddr, u8 addr[6],
unsigned long data; unsigned long data;
data = (addr[5] << 8) | addr[4]; 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]; data = (addr[3] << 24) | (addr[2] << 16) | (addr[1] << 8) | addr[0];
writel(data, ioaddr + low); writel(data, ioaddr + low);
} }
......
...@@ -85,6 +85,7 @@ struct stmmac_priv { ...@@ -85,6 +85,7 @@ struct stmmac_priv {
struct clk *stmmac_clk; struct clk *stmmac_clk;
#endif #endif
int clk_csr; int clk_csr;
int synopsys_id;
}; };
extern int phyaddr; extern int phyaddr;
......
...@@ -1465,7 +1465,7 @@ static void stmmac_set_rx_mode(struct net_device *dev) ...@@ -1465,7 +1465,7 @@ static void stmmac_set_rx_mode(struct net_device *dev)
struct stmmac_priv *priv = netdev_priv(dev); struct stmmac_priv *priv = netdev_priv(dev);
spin_lock(&priv->lock); spin_lock(&priv->lock);
priv->hw->mac->set_filter(dev); priv->hw->mac->set_filter(dev, priv->synopsys_id);
spin_unlock(&priv->lock); spin_unlock(&priv->lock);
} }
...@@ -1806,7 +1806,7 @@ static int stmmac_hw_init(struct stmmac_priv *priv) ...@@ -1806,7 +1806,7 @@ static int stmmac_hw_init(struct stmmac_priv *priv)
priv->hw->ring = &ring_mode_ops; priv->hw->ring = &ring_mode_ops;
/* Get and dump the chip ID */ /* 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) */ /* Get the HW capability (new GMAC newer than 3.50a) */
priv->hw_cap_support = stmmac_get_hw_features(priv); priv->hw_cap_support = stmmac_get_hw_features(priv);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment