aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/stmmac/dwmac100_core.c
diff options
context:
space:
mode:
authorGiuseppe CAVALLARO <peppe.cavallaro@st.com>2010-04-13 16:21:11 -0400
committerDavid S. Miller <davem@davemloft.net>2010-04-14 07:49:49 -0400
commit3c32be635c18ead00d460b7bdad1da52622ff40f (patch)
tree5a26fc20ebe0b826fc3deb66676b20897ac8e979 /drivers/net/stmmac/dwmac100_core.c
parentf0ad0860d01e47a3ffd220564c5c653b3afbe962 (diff)
stmmac: split core and dma for the mac10/100
The patch splits core and dma parts for the mac10/100 device. This was already done for the GMAC device. It should make more flexible the driver to support other chips. Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/stmmac/dwmac100_core.c')
-rw-r--r--drivers/net/stmmac/dwmac100_core.c202
1 files changed, 202 insertions, 0 deletions
diff --git a/drivers/net/stmmac/dwmac100_core.c b/drivers/net/stmmac/dwmac100_core.c
new file mode 100644
index 00000000000..8ecb8c0b4d9
--- /dev/null
+++ b/drivers/net/stmmac/dwmac100_core.c
@@ -0,0 +1,202 @@
1/*******************************************************************************
2 This is the driver for the MAC 10/100 on-chip Ethernet controller
3 currently tested on all the ST boards based on STb7109 and stx7200 SoCs.
4
5 DWC Ether MAC 10/100 Universal version 4.0 has been used for developing
6 this code.
7
8 This only implements the mac core functions for this chip.
9
10 Copyright (C) 2007-2009 STMicroelectronics Ltd
11
12 This program is free software; you can redistribute it and/or modify it
13 under the terms and conditions of the GNU General Public License,
14 version 2, as published by the Free Software Foundation.
15
16 This program is distributed in the hope it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
19 more details.
20
21 You should have received a copy of the GNU General Public License along with
22 this program; if not, write to the Free Software Foundation, Inc.,
23 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
24
25 The full GNU General Public License is included in this distribution in
26 the file called "COPYING".
27
28 Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
29*******************************************************************************/
30
31#include <linux/crc32.h>
32#include "dwmac100.h"
33
34static void dwmac100_core_init(unsigned long ioaddr)
35{
36 u32 value = readl(ioaddr + MAC_CONTROL);
37
38 writel((value | MAC_CORE_INIT), ioaddr + MAC_CONTROL);
39
40#ifdef STMMAC_VLAN_TAG_USED
41 writel(ETH_P_8021Q, ioaddr + MAC_VLAN1);
42#endif
43 return;
44}
45
46static void dwmac100_dump_mac_regs(unsigned long ioaddr)
47{
48 pr_info("\t----------------------------------------------\n"
49 "\t DWMAC 100 CSR (base addr = 0x%8x)\n"
50 "\t----------------------------------------------\n",
51 (unsigned int)ioaddr);
52 pr_info("\tcontrol reg (offset 0x%x): 0x%08x\n", MAC_CONTROL,
53 readl(ioaddr + MAC_CONTROL));
54 pr_info("\taddr HI (offset 0x%x): 0x%08x\n ", MAC_ADDR_HIGH,
55 readl(ioaddr + MAC_ADDR_HIGH));
56 pr_info("\taddr LO (offset 0x%x): 0x%08x\n", MAC_ADDR_LOW,
57 readl(ioaddr + MAC_ADDR_LOW));
58 pr_info("\tmulticast hash HI (offset 0x%x): 0x%08x\n",
59 MAC_HASH_HIGH, readl(ioaddr + MAC_HASH_HIGH));
60 pr_info("\tmulticast hash LO (offset 0x%x): 0x%08x\n",
61 MAC_HASH_LOW, readl(ioaddr + MAC_HASH_LOW));
62 pr_info("\tflow control (offset 0x%x): 0x%08x\n",
63 MAC_FLOW_CTRL, readl(ioaddr + MAC_FLOW_CTRL));
64 pr_info("\tVLAN1 tag (offset 0x%x): 0x%08x\n", MAC_VLAN1,
65 readl(ioaddr + MAC_VLAN1));
66 pr_info("\tVLAN2 tag (offset 0x%x): 0x%08x\n", MAC_VLAN2,
67 readl(ioaddr + MAC_VLAN2));
68 pr_info("\n\tMAC management counter registers\n");
69 pr_info("\t MMC crtl (offset 0x%x): 0x%08x\n",
70 MMC_CONTROL, readl(ioaddr + MMC_CONTROL));
71 pr_info("\t MMC High Interrupt (offset 0x%x): 0x%08x\n",
72 MMC_HIGH_INTR, readl(ioaddr + MMC_HIGH_INTR));
73 pr_info("\t MMC Low Interrupt (offset 0x%x): 0x%08x\n",
74 MMC_LOW_INTR, readl(ioaddr + MMC_LOW_INTR));
75 pr_info("\t MMC High Interrupt Mask (offset 0x%x): 0x%08x\n",
76 MMC_HIGH_INTR_MASK, readl(ioaddr + MMC_HIGH_INTR_MASK));
77 pr_info("\t MMC Low Interrupt Mask (offset 0x%x): 0x%08x\n",
78 MMC_LOW_INTR_MASK, readl(ioaddr + MMC_LOW_INTR_MASK));
79 return;
80}
81
82static void dwmac100_irq_status(unsigned long ioaddr)
83{
84 return;
85}
86
87static void dwmac100_set_umac_addr(unsigned long ioaddr, unsigned char *addr,
88 unsigned int reg_n)
89{
90 stmmac_set_mac_addr(ioaddr, addr, MAC_ADDR_HIGH, MAC_ADDR_LOW);
91}
92
93static void dwmac100_get_umac_addr(unsigned long ioaddr, unsigned char *addr,
94 unsigned int reg_n)
95{
96 stmmac_get_mac_addr(ioaddr, addr, MAC_ADDR_HIGH, MAC_ADDR_LOW);
97}
98
99static void dwmac100_set_filter(struct net_device *dev)
100{
101 unsigned long ioaddr = dev->base_addr;
102 u32 value = readl(ioaddr + MAC_CONTROL);
103
104 if (dev->flags & IFF_PROMISC) {
105 value |= MAC_CONTROL_PR;
106 value &= ~(MAC_CONTROL_PM | MAC_CONTROL_IF | MAC_CONTROL_HO |
107 MAC_CONTROL_HP);
108 } else if ((netdev_mc_count(dev) > HASH_TABLE_SIZE)
109 || (dev->flags & IFF_ALLMULTI)) {
110 value |= MAC_CONTROL_PM;
111 value &= ~(MAC_CONTROL_PR | MAC_CONTROL_IF | MAC_CONTROL_HO);
112 writel(0xffffffff, ioaddr + MAC_HASH_HIGH);
113 writel(0xffffffff, ioaddr + MAC_HASH_LOW);
114 } else if (netdev_mc_empty(dev)) { /* no multicast */
115 value &= ~(MAC_CONTROL_PM | MAC_CONTROL_PR | MAC_CONTROL_IF |
116 MAC_CONTROL_HO | MAC_CONTROL_HP);
117 } else {
118 u32 mc_filter[2];
119 struct netdev_hw_addr *ha;
120
121 /* Perfect filter mode for physical address and Hash
122 filter for multicast */
123 value |= MAC_CONTROL_HP;
124 value &= ~(MAC_CONTROL_PM | MAC_CONTROL_PR |
125 MAC_CONTROL_IF | MAC_CONTROL_HO);
126
127 memset(mc_filter, 0, sizeof(mc_filter));
128 netdev_for_each_mc_addr(ha, dev) {
129 /* The upper 6 bits of the calculated CRC are used to
130 * index the contens of the hash table */
131 int bit_nr =
132 ether_crc(ETH_ALEN, ha->addr) >> 26;
133 /* The most significant bit determines the register to
134 * use (H/L) while the other 5 bits determine the bit
135 * within the register. */
136 mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31);
137 }
138 writel(mc_filter[0], ioaddr + MAC_HASH_LOW);
139 writel(mc_filter[1], ioaddr + MAC_HASH_HIGH);
140 }
141
142 writel(value, ioaddr + MAC_CONTROL);
143
144 DBG(KERN_INFO "%s: CTRL reg: 0x%08x Hash regs: "
145 "HI 0x%08x, LO 0x%08x\n",
146 __func__, readl(ioaddr + MAC_CONTROL),
147 readl(ioaddr + MAC_HASH_HIGH), readl(ioaddr + MAC_HASH_LOW));
148 return;
149}
150
151static void dwmac100_flow_ctrl(unsigned long ioaddr, unsigned int duplex,
152 unsigned int fc, unsigned int pause_time)
153{
154 unsigned int flow = MAC_FLOW_CTRL_ENABLE;
155
156 if (duplex)
157 flow |= (pause_time << MAC_FLOW_CTRL_PT_SHIFT);
158 writel(flow, ioaddr + MAC_FLOW_CTRL);
159
160 return;
161}
162
163/* No PMT module supported for this Ethernet Controller.
164 * Tested on ST platforms only.
165 */
166static void dwmac100_pmt(unsigned long ioaddr, unsigned long mode)
167{
168 return;
169}
170
171struct stmmac_ops dwmac100_ops = {
172 .core_init = dwmac100_core_init,
173 .dump_regs = dwmac100_dump_mac_regs,
174 .host_irq_status = dwmac100_irq_status,
175 .set_filter = dwmac100_set_filter,
176 .flow_ctrl = dwmac100_flow_ctrl,
177 .pmt = dwmac100_pmt,
178 .set_umac_addr = dwmac100_set_umac_addr,
179 .get_umac_addr = dwmac100_get_umac_addr,
180};
181
182struct mac_device_info *dwmac100_setup(unsigned long ioaddr)
183{
184 struct mac_device_info *mac;
185
186 mac = kzalloc(sizeof(const struct mac_device_info), GFP_KERNEL);
187
188 pr_info("\tDWMAC100\n");
189
190 mac->mac = &dwmac100_ops;
191 mac->desc = &dwmac100_desc_ops;
192 mac->dma = &dwmac100_dma_ops;
193
194 mac->pmt = PMT_NOT_SUPPORTED;
195 mac->link.port = MAC_CONTROL_PS;
196 mac->link.duplex = MAC_CONTROL_F;
197 mac->link.speed = 0;
198 mac->mii.addr = MAC_MII_ADDR;
199 mac->mii.data = MAC_MII_DATA;
200
201 return mac;
202}