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.
6 DWC Ether MAC 10/100 Universal version 4.0 has been used for developing
9 This only implements the mac core functions for this chip.
11 Copyright (C) 2007-2009 STMicroelectronics Ltd
14 Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
15 *******************************************************************************/
17 #include <linux/crc32.h>
23 static void dwmac100_core_init(struct mac_device_info
*hw
,
24 struct net_device
*dev
)
26 void __iomem
*ioaddr
= hw
->pcsr
;
27 u32 value
= readl(ioaddr
+ MAC_CONTROL
);
29 value
|= MAC_CORE_INIT
;
31 /* Clear ASTP bit because Ethernet switch tagging formats such as
32 * Broadcom tags can look like invalid LLC/SNAP packets and cause the
33 * hardware to truncate packets on reception.
35 if (netdev_uses_dsa(dev
))
36 value
&= ~MAC_CONTROL_ASTP
;
38 writel(value
, ioaddr
+ MAC_CONTROL
);
40 #ifdef STMMAC_VLAN_TAG_USED
41 writel(ETH_P_8021Q
, ioaddr
+ MAC_VLAN1
);
45 static void dwmac100_dump_mac_regs(struct mac_device_info
*hw
, u32
*reg_space
)
47 void __iomem
*ioaddr
= hw
->pcsr
;
49 reg_space
[MAC_CONTROL
/ 4] = readl(ioaddr
+ MAC_CONTROL
);
50 reg_space
[MAC_ADDR_HIGH
/ 4] = readl(ioaddr
+ MAC_ADDR_HIGH
);
51 reg_space
[MAC_ADDR_LOW
/ 4] = readl(ioaddr
+ MAC_ADDR_LOW
);
52 reg_space
[MAC_HASH_HIGH
/ 4] = readl(ioaddr
+ MAC_HASH_HIGH
);
53 reg_space
[MAC_HASH_LOW
/ 4] = readl(ioaddr
+ MAC_HASH_LOW
);
54 reg_space
[MAC_FLOW_CTRL
/ 4] = readl(ioaddr
+ MAC_FLOW_CTRL
);
55 reg_space
[MAC_VLAN1
/ 4] = readl(ioaddr
+ MAC_VLAN1
);
56 reg_space
[MAC_VLAN2
/ 4] = readl(ioaddr
+ MAC_VLAN2
);
59 static int dwmac100_rx_ipc_enable(struct mac_device_info
*hw
)
64 static int dwmac100_irq_status(struct mac_device_info
*hw
,
65 struct stmmac_extra_stats
*x
)
70 static void dwmac100_set_umac_addr(struct mac_device_info
*hw
,
74 void __iomem
*ioaddr
= hw
->pcsr
;
75 stmmac_set_mac_addr(ioaddr
, addr
, MAC_ADDR_HIGH
, MAC_ADDR_LOW
);
78 static void dwmac100_get_umac_addr(struct mac_device_info
*hw
,
82 void __iomem
*ioaddr
= hw
->pcsr
;
83 stmmac_get_mac_addr(ioaddr
, addr
, MAC_ADDR_HIGH
, MAC_ADDR_LOW
);
86 static void dwmac100_set_filter(struct mac_device_info
*hw
,
87 struct net_device
*dev
)
89 void __iomem
*ioaddr
= (void __iomem
*)dev
->base_addr
;
90 u32 value
= readl(ioaddr
+ MAC_CONTROL
);
92 if (dev
->flags
& IFF_PROMISC
) {
93 value
|= MAC_CONTROL_PR
;
94 value
&= ~(MAC_CONTROL_PM
| MAC_CONTROL_IF
| MAC_CONTROL_HO
|
96 } else if ((netdev_mc_count(dev
) > HASH_TABLE_SIZE
)
97 || (dev
->flags
& IFF_ALLMULTI
)) {
98 value
|= MAC_CONTROL_PM
;
99 value
&= ~(MAC_CONTROL_PR
| MAC_CONTROL_IF
| MAC_CONTROL_HO
);
100 writel(0xffffffff, ioaddr
+ MAC_HASH_HIGH
);
101 writel(0xffffffff, ioaddr
+ MAC_HASH_LOW
);
102 } else if (netdev_mc_empty(dev
)) { /* no multicast */
103 value
&= ~(MAC_CONTROL_PM
| MAC_CONTROL_PR
| MAC_CONTROL_IF
|
104 MAC_CONTROL_HO
| MAC_CONTROL_HP
);
107 struct netdev_hw_addr
*ha
;
109 /* Perfect filter mode for physical address and Hash
110 * filter for multicast
112 value
|= MAC_CONTROL_HP
;
113 value
&= ~(MAC_CONTROL_PM
| MAC_CONTROL_PR
|
114 MAC_CONTROL_IF
| MAC_CONTROL_HO
);
116 memset(mc_filter
, 0, sizeof(mc_filter
));
117 netdev_for_each_mc_addr(ha
, dev
) {
118 /* The upper 6 bits of the calculated CRC are used to
119 * index the contens of the hash table
121 int bit_nr
= ether_crc(ETH_ALEN
, ha
->addr
) >> 26;
122 /* The most significant bit determines the register to
123 * use (H/L) while the other 5 bits determine the bit
124 * within the register.
126 mc_filter
[bit_nr
>> 5] |= 1 << (bit_nr
& 31);
128 writel(mc_filter
[0], ioaddr
+ MAC_HASH_LOW
);
129 writel(mc_filter
[1], ioaddr
+ MAC_HASH_HIGH
);
132 writel(value
, ioaddr
+ MAC_CONTROL
);
135 static void dwmac100_flow_ctrl(struct mac_device_info
*hw
, unsigned int duplex
,
136 unsigned int fc
, unsigned int pause_time
,
139 void __iomem
*ioaddr
= hw
->pcsr
;
140 unsigned int flow
= MAC_FLOW_CTRL_ENABLE
;
143 flow
|= (pause_time
<< MAC_FLOW_CTRL_PT_SHIFT
);
144 writel(flow
, ioaddr
+ MAC_FLOW_CTRL
);
147 /* No PMT module supported on ST boards with this Eth chip. */
148 static void dwmac100_pmt(struct mac_device_info
*hw
, unsigned long mode
)
153 static void dwmac100_set_mac_loopback(void __iomem
*ioaddr
, bool enable
)
155 u32 value
= readl(ioaddr
+ MAC_CONTROL
);
158 value
|= MAC_CONTROL_OM
;
160 value
&= ~MAC_CONTROL_OM
;
162 writel(value
, ioaddr
+ MAC_CONTROL
);
165 const struct stmmac_ops dwmac100_ops
= {
166 .core_init
= dwmac100_core_init
,
167 .set_mac
= stmmac_set_mac
,
168 .rx_ipc
= dwmac100_rx_ipc_enable
,
169 .dump_regs
= dwmac100_dump_mac_regs
,
170 .host_irq_status
= dwmac100_irq_status
,
171 .set_filter
= dwmac100_set_filter
,
172 .flow_ctrl
= dwmac100_flow_ctrl
,
174 .set_umac_addr
= dwmac100_set_umac_addr
,
175 .get_umac_addr
= dwmac100_get_umac_addr
,
176 .set_mac_loopback
= dwmac100_set_mac_loopback
,
179 int dwmac100_setup(struct stmmac_priv
*priv
)
181 struct mac_device_info
*mac
= priv
->hw
;
183 dev_info(priv
->device
, "\tDWMAC100\n");
185 mac
->pcsr
= priv
->ioaddr
;
186 mac
->link
.duplex
= MAC_CONTROL_F
;
187 mac
->link
.speed10
= 0;
188 mac
->link
.speed100
= 0;
189 mac
->link
.speed1000
= 0;
190 mac
->link
.speed_mask
= MAC_CONTROL_PS
;
191 mac
->mii
.addr
= MAC_MII_ADDR
;
192 mac
->mii
.data
= MAC_MII_DATA
;
193 mac
->mii
.addr_shift
= 11;
194 mac
->mii
.addr_mask
= 0x0000F800;
195 mac
->mii
.reg_shift
= 6;
196 mac
->mii
.reg_mask
= 0x000007C0;
197 mac
->mii
.clk_csr_shift
= 2;
198 mac
->mii
.clk_csr_mask
= GENMASK(5, 2);