diff options
author | Giuseppe CAVALLARO <peppe.cavallaro@st.com> | 2010-01-06 18:07:20 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-01-07 20:06:10 -0500 |
commit | 21d437cc66dcfd0119a4905214fbbe19f3e276dc (patch) | |
tree | a633c68d6ebd89ce2a55efb26040c6a6372e9416 /drivers/net/stmmac/dwmac1000_core.c | |
parent | 7e848ae113ca7442ba6b44168fa2238224f37e8a (diff) |
stmmac: rename the gmac as dwmac1000 and split core and dma parts
Use dwmac1000 naming instead of gmac.
The patch also splits the gmac.c file in two new ones:
dwmac1000_core.c and dwmac1000_dma.c.
This could actually help on some architectures where different
DMA engines are used.
Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/stmmac/dwmac1000_core.c')
-rw-r--r-- | drivers/net/stmmac/dwmac1000_core.c | 245 |
1 files changed, 245 insertions, 0 deletions
diff --git a/drivers/net/stmmac/dwmac1000_core.c b/drivers/net/stmmac/dwmac1000_core.c new file mode 100644 index 00000000000..928eac05b91 --- /dev/null +++ b/drivers/net/stmmac/dwmac1000_core.c | |||
@@ -0,0 +1,245 @@ | |||
1 | /******************************************************************************* | ||
2 | This is the driver for the GMAC on-chip Ethernet controller for ST SoCs. | ||
3 | DWC Ether MAC 10/100/1000 Universal version 3.41a has been used for | ||
4 | developing this code. | ||
5 | |||
6 | This only implements the mac core functions for this chip. | ||
7 | |||
8 | Copyright (C) 2007-2009 STMicroelectronics Ltd | ||
9 | |||
10 | This program is free software; you can redistribute it and/or modify it | ||
11 | under the terms and conditions of the GNU General Public License, | ||
12 | version 2, as published by the Free Software Foundation. | ||
13 | |||
14 | This program is distributed in the hope it will be useful, but WITHOUT | ||
15 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
16 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
17 | more details. | ||
18 | |||
19 | You should have received a copy of the GNU General Public License along with | ||
20 | this program; if not, write to the Free Software Foundation, Inc., | ||
21 | 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
22 | |||
23 | The full GNU General Public License is included in this distribution in | ||
24 | the file called "COPYING". | ||
25 | |||
26 | Author: Giuseppe Cavallaro <peppe.cavallaro@st.com> | ||
27 | *******************************************************************************/ | ||
28 | |||
29 | #include <linux/crc32.h> | ||
30 | #include "dwmac1000.h" | ||
31 | |||
32 | static void dwmac1000_core_init(unsigned long ioaddr) | ||
33 | { | ||
34 | u32 value = readl(ioaddr + GMAC_CONTROL); | ||
35 | value |= GMAC_CORE_INIT; | ||
36 | writel(value, ioaddr + GMAC_CONTROL); | ||
37 | |||
38 | /* STBus Bridge Configuration */ | ||
39 | /*writel(0xc5608, ioaddr + 0x00007000);*/ | ||
40 | |||
41 | /* Freeze MMC counters */ | ||
42 | writel(0x8, ioaddr + GMAC_MMC_CTRL); | ||
43 | /* Mask GMAC interrupts */ | ||
44 | writel(0x207, ioaddr + GMAC_INT_MASK); | ||
45 | |||
46 | #ifdef STMMAC_VLAN_TAG_USED | ||
47 | /* Tag detection without filtering */ | ||
48 | writel(0x0, ioaddr + GMAC_VLAN_TAG); | ||
49 | #endif | ||
50 | return; | ||
51 | } | ||
52 | |||
53 | static void dwmac1000_dump_regs(unsigned long ioaddr) | ||
54 | { | ||
55 | int i; | ||
56 | pr_info("\tDWMAC1000 regs (base addr = 0x%8x)\n", (unsigned int)ioaddr); | ||
57 | |||
58 | for (i = 0; i < 55; i++) { | ||
59 | int offset = i * 4; | ||
60 | pr_info("\tReg No. %d (offset 0x%x): 0x%08x\n", i, | ||
61 | offset, readl(ioaddr + offset)); | ||
62 | } | ||
63 | return; | ||
64 | } | ||
65 | |||
66 | static void dwmac1000_set_umac_addr(unsigned long ioaddr, unsigned char *addr, | ||
67 | unsigned int reg_n) | ||
68 | { | ||
69 | stmmac_set_mac_addr(ioaddr, addr, GMAC_ADDR_HIGH(reg_n), | ||
70 | GMAC_ADDR_LOW(reg_n)); | ||
71 | } | ||
72 | |||
73 | static void dwmac1000_get_umac_addr(unsigned long ioaddr, unsigned char *addr, | ||
74 | unsigned int reg_n) | ||
75 | { | ||
76 | stmmac_get_mac_addr(ioaddr, addr, GMAC_ADDR_HIGH(reg_n), | ||
77 | GMAC_ADDR_LOW(reg_n)); | ||
78 | } | ||
79 | |||
80 | static void dwmac1000_set_filter(struct net_device *dev) | ||
81 | { | ||
82 | unsigned long ioaddr = dev->base_addr; | ||
83 | unsigned int value = 0; | ||
84 | |||
85 | DBG(KERN_INFO "%s: # mcasts %d, # unicast %d\n", | ||
86 | __func__, dev->mc_count, dev->uc.count); | ||
87 | |||
88 | if (dev->flags & IFF_PROMISC) | ||
89 | value = GMAC_FRAME_FILTER_PR; | ||
90 | else if ((dev->mc_count > HASH_TABLE_SIZE) | ||
91 | || (dev->flags & IFF_ALLMULTI)) { | ||
92 | value = GMAC_FRAME_FILTER_PM; /* pass all multi */ | ||
93 | writel(0xffffffff, ioaddr + GMAC_HASH_HIGH); | ||
94 | writel(0xffffffff, ioaddr + GMAC_HASH_LOW); | ||
95 | } else if (dev->mc_count > 0) { | ||
96 | int i; | ||
97 | u32 mc_filter[2]; | ||
98 | struct dev_mc_list *mclist; | ||
99 | |||
100 | /* Hash filter for multicast */ | ||
101 | value = GMAC_FRAME_FILTER_HMC; | ||
102 | |||
103 | memset(mc_filter, 0, sizeof(mc_filter)); | ||
104 | for (i = 0, mclist = dev->mc_list; | ||
105 | mclist && i < dev->mc_count; i++, mclist = mclist->next) { | ||
106 | /* The upper 6 bits of the calculated CRC are used to | ||
107 | index the contens of the hash table */ | ||
108 | int bit_nr = | ||
109 | bitrev32(~crc32_le(~0, mclist->dmi_addr, 6)) >> 26; | ||
110 | /* The most significant bit determines the register to | ||
111 | * use (H/L) while the other 5 bits determine the bit | ||
112 | * within the register. */ | ||
113 | mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); | ||
114 | } | ||
115 | writel(mc_filter[0], ioaddr + GMAC_HASH_LOW); | ||
116 | writel(mc_filter[1], ioaddr + GMAC_HASH_HIGH); | ||
117 | } | ||
118 | |||
119 | /* Handle multiple unicast addresses (perfect filtering)*/ | ||
120 | if (dev->uc.count > GMAC_MAX_UNICAST_ADDRESSES) | ||
121 | /* Switch to promiscuous mode is more than 16 addrs | ||
122 | are required */ | ||
123 | value |= GMAC_FRAME_FILTER_PR; | ||
124 | else { | ||
125 | int reg = 1; | ||
126 | struct netdev_hw_addr *ha; | ||
127 | |||
128 | list_for_each_entry(ha, &dev->uc.list, list) { | ||
129 | dwmac1000_set_umac_addr(ioaddr, ha->addr, reg); | ||
130 | reg++; | ||
131 | } | ||
132 | } | ||
133 | |||
134 | #ifdef FRAME_FILTER_DEBUG | ||
135 | /* Enable Receive all mode (to debug filtering_fail errors) */ | ||
136 | value |= GMAC_FRAME_FILTER_RA; | ||
137 | #endif | ||
138 | writel(value, ioaddr + GMAC_FRAME_FILTER); | ||
139 | |||
140 | DBG(KERN_INFO "\tFrame Filter reg: 0x%08x\n\tHash regs: " | ||
141 | "HI 0x%08x, LO 0x%08x\n", readl(ioaddr + GMAC_FRAME_FILTER), | ||
142 | readl(ioaddr + GMAC_HASH_HIGH), readl(ioaddr + GMAC_HASH_LOW)); | ||
143 | |||
144 | return; | ||
145 | } | ||
146 | |||
147 | static void dwmac1000_flow_ctrl(unsigned long ioaddr, unsigned int duplex, | ||
148 | unsigned int fc, unsigned int pause_time) | ||
149 | { | ||
150 | unsigned int flow = 0; | ||
151 | |||
152 | DBG(KERN_DEBUG "GMAC Flow-Control:\n"); | ||
153 | if (fc & FLOW_RX) { | ||
154 | DBG(KERN_DEBUG "\tReceive Flow-Control ON\n"); | ||
155 | flow |= GMAC_FLOW_CTRL_RFE; | ||
156 | } | ||
157 | if (fc & FLOW_TX) { | ||
158 | DBG(KERN_DEBUG "\tTransmit Flow-Control ON\n"); | ||
159 | flow |= GMAC_FLOW_CTRL_TFE; | ||
160 | } | ||
161 | |||
162 | if (duplex) { | ||
163 | DBG(KERN_DEBUG "\tduplex mode: pause time: %d\n", pause_time); | ||
164 | flow |= (pause_time << GMAC_FLOW_CTRL_PT_SHIFT); | ||
165 | } | ||
166 | |||
167 | writel(flow, ioaddr + GMAC_FLOW_CTRL); | ||
168 | return; | ||
169 | } | ||
170 | |||
171 | static void dwmac1000_pmt(unsigned long ioaddr, unsigned long mode) | ||
172 | { | ||
173 | unsigned int pmt = 0; | ||
174 | |||
175 | if (mode == WAKE_MAGIC) { | ||
176 | DBG(KERN_DEBUG "GMAC: WOL Magic frame\n"); | ||
177 | pmt |= power_down | magic_pkt_en; | ||
178 | } else if (mode == WAKE_UCAST) { | ||
179 | DBG(KERN_DEBUG "GMAC: WOL on global unicast\n"); | ||
180 | pmt |= global_unicast; | ||
181 | } | ||
182 | |||
183 | writel(pmt, ioaddr + GMAC_PMT); | ||
184 | return; | ||
185 | } | ||
186 | |||
187 | |||
188 | static void dwmac1000_irq_status(unsigned long ioaddr) | ||
189 | { | ||
190 | u32 intr_status = readl(ioaddr + GMAC_INT_STATUS); | ||
191 | |||
192 | /* Not used events (e.g. MMC interrupts) are not handled. */ | ||
193 | if ((intr_status & mmc_tx_irq)) | ||
194 | DBG(KERN_DEBUG "GMAC: MMC tx interrupt: 0x%08x\n", | ||
195 | readl(ioaddr + GMAC_MMC_TX_INTR)); | ||
196 | if (unlikely(intr_status & mmc_rx_irq)) | ||
197 | DBG(KERN_DEBUG "GMAC: MMC rx interrupt: 0x%08x\n", | ||
198 | readl(ioaddr + GMAC_MMC_RX_INTR)); | ||
199 | if (unlikely(intr_status & mmc_rx_csum_offload_irq)) | ||
200 | DBG(KERN_DEBUG "GMAC: MMC rx csum offload: 0x%08x\n", | ||
201 | readl(ioaddr + GMAC_MMC_RX_CSUM_OFFLOAD)); | ||
202 | if (unlikely(intr_status & pmt_irq)) { | ||
203 | DBG(KERN_DEBUG "GMAC: received Magic frame\n"); | ||
204 | /* clear the PMT bits 5 and 6 by reading the PMT | ||
205 | * status register. */ | ||
206 | readl(ioaddr + GMAC_PMT); | ||
207 | } | ||
208 | |||
209 | return; | ||
210 | } | ||
211 | |||
212 | struct stmmac_ops dwmac1000_ops = { | ||
213 | .core_init = dwmac1000_core_init, | ||
214 | .dump_regs = dwmac1000_dump_regs, | ||
215 | .host_irq_status = dwmac1000_irq_status, | ||
216 | .set_filter = dwmac1000_set_filter, | ||
217 | .flow_ctrl = dwmac1000_flow_ctrl, | ||
218 | .pmt = dwmac1000_pmt, | ||
219 | .set_umac_addr = dwmac1000_set_umac_addr, | ||
220 | .get_umac_addr = dwmac1000_get_umac_addr, | ||
221 | }; | ||
222 | |||
223 | struct mac_device_info *dwmac1000_setup(unsigned long ioaddr) | ||
224 | { | ||
225 | struct mac_device_info *mac; | ||
226 | u32 uid = readl(ioaddr + GMAC_VERSION); | ||
227 | |||
228 | pr_info("\tDWMAC1000 - user ID: 0x%x, Synopsys ID: 0x%x\n", | ||
229 | ((uid & 0x0000ff00) >> 8), (uid & 0x000000ff)); | ||
230 | |||
231 | mac = kzalloc(sizeof(const struct mac_device_info), GFP_KERNEL); | ||
232 | |||
233 | mac->mac = &dwmac1000_ops; | ||
234 | mac->desc = &dwmac1000_desc_ops; | ||
235 | mac->dma = &dwmac1000_dma_ops; | ||
236 | |||
237 | mac->pmt = PMT_SUPPORTED; | ||
238 | mac->link.port = GMAC_CONTROL_PS; | ||
239 | mac->link.duplex = GMAC_CONTROL_DM; | ||
240 | mac->link.speed = GMAC_CONTROL_FES; | ||
241 | mac->mii.addr = GMAC_MII_ADDR; | ||
242 | mac->mii.data = GMAC_MII_DATA; | ||
243 | |||
244 | return mac; | ||
245 | } | ||