1 // SPDX-License-Identifier: GPL-2.0-only 2 /******************************************************************************* 3 This is the driver for the MAC 10/100 on-chip Ethernet controller 4 currently tested on all the ST boards based on STb7109 and stx7200 SoCs. 5 6 DWC Ether MAC 10/100 Universal version 4.0 has been used for developing 7 this code. 8 9 This only implements the mac core functions for this chip. 10 11 Copyright (C) 2007-2009 STMicroelectronics Ltd 12 13 14 Author: Giuseppe Cavallaro <peppe.cavallaro@st.com> 15 *******************************************************************************/ 16 17 #include <linux/crc32.h> 18 #include <asm/io.h> 19 #include "stmmac.h" 20 #include "dwmac100.h" 21 22 static void dwmac100_core_init(struct mac_device_info *hw, 23 struct net_device *dev) 24 { 25 void __iomem *ioaddr = hw->pcsr; 26 u32 value = readl(ioaddr + MAC_CONTROL); 27 28 value |= MAC_CORE_INIT; 29 30 writel(value, ioaddr + MAC_CONTROL); 31 32 #ifdef STMMAC_VLAN_TAG_USED 33 writel(ETH_P_8021Q, ioaddr + MAC_VLAN1); 34 #endif 35 } 36 37 static void dwmac100_dump_mac_regs(struct mac_device_info *hw, u32 *reg_space) 38 { 39 void __iomem *ioaddr = hw->pcsr; 40 41 reg_space[MAC_CONTROL / 4] = readl(ioaddr + MAC_CONTROL); 42 reg_space[MAC_ADDR_HIGH / 4] = readl(ioaddr + MAC_ADDR_HIGH); 43 reg_space[MAC_ADDR_LOW / 4] = readl(ioaddr + MAC_ADDR_LOW); 44 reg_space[MAC_HASH_HIGH / 4] = readl(ioaddr + MAC_HASH_HIGH); 45 reg_space[MAC_HASH_LOW / 4] = readl(ioaddr + MAC_HASH_LOW); 46 reg_space[MAC_FLOW_CTRL / 4] = readl(ioaddr + MAC_FLOW_CTRL); 47 reg_space[MAC_VLAN1 / 4] = readl(ioaddr + MAC_VLAN1); 48 reg_space[MAC_VLAN2 / 4] = readl(ioaddr + MAC_VLAN2); 49 } 50 51 static int dwmac100_rx_ipc_enable(struct mac_device_info *hw) 52 { 53 return 0; 54 } 55 56 static int dwmac100_irq_status(struct mac_device_info *hw, 57 struct stmmac_extra_stats *x) 58 { 59 return 0; 60 } 61 62 static void dwmac100_set_umac_addr(struct mac_device_info *hw, 63 const unsigned char *addr, 64 unsigned int reg_n) 65 { 66 void __iomem *ioaddr = hw->pcsr; 67 stmmac_set_mac_addr(ioaddr, addr, MAC_ADDR_HIGH, MAC_ADDR_LOW); 68 } 69 70 static void dwmac100_get_umac_addr(struct mac_device_info *hw, 71 unsigned char *addr, 72 unsigned int reg_n) 73 { 74 void __iomem *ioaddr = hw->pcsr; 75 stmmac_get_mac_addr(ioaddr, addr, MAC_ADDR_HIGH, MAC_ADDR_LOW); 76 } 77 78 static void dwmac100_set_filter(struct mac_device_info *hw, 79 struct net_device *dev) 80 { 81 void __iomem *ioaddr = (void __iomem *)dev->base_addr; 82 u32 value = readl(ioaddr + MAC_CONTROL); 83 84 if (dev->flags & IFF_PROMISC) { 85 value |= MAC_CONTROL_PR; 86 value &= ~(MAC_CONTROL_PM | MAC_CONTROL_IF | MAC_CONTROL_HO | 87 MAC_CONTROL_HP); 88 } else if ((netdev_mc_count(dev) > HASH_TABLE_SIZE) 89 || (dev->flags & IFF_ALLMULTI)) { 90 value |= MAC_CONTROL_PM; 91 value &= ~(MAC_CONTROL_PR | MAC_CONTROL_IF | MAC_CONTROL_HO); 92 writel(0xffffffff, ioaddr + MAC_HASH_HIGH); 93 writel(0xffffffff, ioaddr + MAC_HASH_LOW); 94 } else if (netdev_mc_empty(dev)) { /* no multicast */ 95 value &= ~(MAC_CONTROL_PM | MAC_CONTROL_PR | MAC_CONTROL_IF | 96 MAC_CONTROL_HO | MAC_CONTROL_HP); 97 } else { 98 u32 mc_filter[2]; 99 struct netdev_hw_addr *ha; 100 101 /* Perfect filter mode for physical address and Hash 102 * filter for multicast 103 */ 104 value |= MAC_CONTROL_HP; 105 value &= ~(MAC_CONTROL_PM | MAC_CONTROL_PR | 106 MAC_CONTROL_IF | MAC_CONTROL_HO); 107 108 memset(mc_filter, 0, sizeof(mc_filter)); 109 netdev_for_each_mc_addr(ha, dev) { 110 /* The upper 6 bits of the calculated CRC are used to 111 * index the contens of the hash table 112 */ 113 int bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26; 114 /* The most significant bit determines the register to 115 * use (H/L) while the other 5 bits determine the bit 116 * within the register. 117 */ 118 mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); 119 } 120 writel(mc_filter[0], ioaddr + MAC_HASH_LOW); 121 writel(mc_filter[1], ioaddr + MAC_HASH_HIGH); 122 } 123 124 writel(value, ioaddr + MAC_CONTROL); 125 } 126 127 static void dwmac100_flow_ctrl(struct mac_device_info *hw, unsigned int duplex, 128 unsigned int fc, unsigned int pause_time, 129 u32 tx_cnt) 130 { 131 void __iomem *ioaddr = hw->pcsr; 132 unsigned int flow = MAC_FLOW_CTRL_ENABLE; 133 134 if (duplex) 135 flow |= (pause_time << MAC_FLOW_CTRL_PT_SHIFT); 136 writel(flow, ioaddr + MAC_FLOW_CTRL); 137 } 138 139 /* No PMT module supported on ST boards with this Eth chip. */ 140 static void dwmac100_pmt(struct mac_device_info *hw, unsigned long mode) 141 { 142 return; 143 } 144 145 static void dwmac100_set_mac_loopback(void __iomem *ioaddr, bool enable) 146 { 147 u32 value = readl(ioaddr + MAC_CONTROL); 148 149 if (enable) 150 value |= MAC_CONTROL_OM; 151 else 152 value &= ~MAC_CONTROL_OM; 153 154 writel(value, ioaddr + MAC_CONTROL); 155 } 156 157 const struct stmmac_ops dwmac100_ops = { 158 .core_init = dwmac100_core_init, 159 .set_mac = stmmac_set_mac, 160 .rx_ipc = dwmac100_rx_ipc_enable, 161 .dump_regs = dwmac100_dump_mac_regs, 162 .host_irq_status = dwmac100_irq_status, 163 .set_filter = dwmac100_set_filter, 164 .flow_ctrl = dwmac100_flow_ctrl, 165 .pmt = dwmac100_pmt, 166 .set_umac_addr = dwmac100_set_umac_addr, 167 .get_umac_addr = dwmac100_get_umac_addr, 168 .set_mac_loopback = dwmac100_set_mac_loopback, 169 }; 170 171 int dwmac100_setup(struct stmmac_priv *priv) 172 { 173 struct mac_device_info *mac = priv->hw; 174 175 dev_info(priv->device, "\tDWMAC100\n"); 176 177 mac->pcsr = priv->ioaddr; 178 mac->link.duplex = MAC_CONTROL_F; 179 mac->link.speed10 = 0; 180 mac->link.speed100 = 0; 181 mac->link.speed1000 = 0; 182 mac->link.speed_mask = MAC_CONTROL_PS; 183 mac->mii.addr = MAC_MII_ADDR; 184 mac->mii.data = MAC_MII_DATA; 185 mac->mii.addr_shift = 11; 186 mac->mii.addr_mask = 0x0000F800; 187 mac->mii.reg_shift = 6; 188 mac->mii.reg_mask = 0x000007C0; 189 mac->mii.clk_csr_shift = 2; 190 mac->mii.clk_csr_mask = GENMASK(5, 2); 191 192 return 0; 193 } 194