]> bbs.cooldavid.org Git - net-next-2.6.git/blame - drivers/net/stmmac/mac100.c
stmmac: move the dma out from the main
[net-next-2.6.git] / drivers / net / stmmac / mac100.c
CommitLineData
47dd7a54
GC
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 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/netdevice.h>
30#include <linux/crc32.h>
31#include <linux/mii.h>
32#include <linux/phy.h>
33
34#include "common.h"
35#include "mac100.h"
aec7ff27 36#include "dwmac_dma.h"
47dd7a54
GC
37
38#undef MAC100_DEBUG
39/*#define MAC100_DEBUG*/
40#ifdef MAC100_DEBUG
41#define DBG(fmt, args...) printk(fmt, ## args)
42#else
43#define DBG(fmt, args...) do { } while (0)
44#endif
45
46static void mac100_core_init(unsigned long ioaddr)
47{
48 u32 value = readl(ioaddr + MAC_CONTROL);
49
50 writel((value | MAC_CORE_INIT), ioaddr + MAC_CONTROL);
51
52#ifdef STMMAC_VLAN_TAG_USED
53 writel(ETH_P_8021Q, ioaddr + MAC_VLAN1);
54#endif
55 return;
56}
57
58static void mac100_dump_mac_regs(unsigned long ioaddr)
59{
60 pr_info("\t----------------------------------------------\n"
61 "\t MAC100 CSR (base addr = 0x%8x)\n"
62 "\t----------------------------------------------\n",
63 (unsigned int)ioaddr);
64 pr_info("\tcontrol reg (offset 0x%x): 0x%08x\n", MAC_CONTROL,
65 readl(ioaddr + MAC_CONTROL));
66 pr_info("\taddr HI (offset 0x%x): 0x%08x\n ", MAC_ADDR_HIGH,
67 readl(ioaddr + MAC_ADDR_HIGH));
68 pr_info("\taddr LO (offset 0x%x): 0x%08x\n", MAC_ADDR_LOW,
69 readl(ioaddr + MAC_ADDR_LOW));
70 pr_info("\tmulticast hash HI (offset 0x%x): 0x%08x\n",
71 MAC_HASH_HIGH, readl(ioaddr + MAC_HASH_HIGH));
72 pr_info("\tmulticast hash LO (offset 0x%x): 0x%08x\n",
73 MAC_HASH_LOW, readl(ioaddr + MAC_HASH_LOW));
74 pr_info("\tflow control (offset 0x%x): 0x%08x\n",
75 MAC_FLOW_CTRL, readl(ioaddr + MAC_FLOW_CTRL));
76 pr_info("\tVLAN1 tag (offset 0x%x): 0x%08x\n", MAC_VLAN1,
77 readl(ioaddr + MAC_VLAN1));
78 pr_info("\tVLAN2 tag (offset 0x%x): 0x%08x\n", MAC_VLAN2,
79 readl(ioaddr + MAC_VLAN2));
80 pr_info("\n\tMAC management counter registers\n");
81 pr_info("\t MMC crtl (offset 0x%x): 0x%08x\n",
82 MMC_CONTROL, readl(ioaddr + MMC_CONTROL));
83 pr_info("\t MMC High Interrupt (offset 0x%x): 0x%08x\n",
84 MMC_HIGH_INTR, readl(ioaddr + MMC_HIGH_INTR));
85 pr_info("\t MMC Low Interrupt (offset 0x%x): 0x%08x\n",
86 MMC_LOW_INTR, readl(ioaddr + MMC_LOW_INTR));
87 pr_info("\t MMC High Interrupt Mask (offset 0x%x): 0x%08x\n",
88 MMC_HIGH_INTR_MASK, readl(ioaddr + MMC_HIGH_INTR_MASK));
89 pr_info("\t MMC Low Interrupt Mask (offset 0x%x): 0x%08x\n",
90 MMC_LOW_INTR_MASK, readl(ioaddr + MMC_LOW_INTR_MASK));
91 return;
92}
93
94static int mac100_dma_init(unsigned long ioaddr, int pbl, u32 dma_tx,
95 u32 dma_rx)
96{
97 u32 value = readl(ioaddr + DMA_BUS_MODE);
98 /* DMA SW reset */
99 value |= DMA_BUS_MODE_SFT_RESET;
100 writel(value, ioaddr + DMA_BUS_MODE);
101 do {} while ((readl(ioaddr + DMA_BUS_MODE) & DMA_BUS_MODE_SFT_RESET));
102
103 /* Enable Application Access by writing to DMA CSR0 */
104 writel(DMA_BUS_MODE_DEFAULT | (pbl << DMA_BUS_MODE_PBL_SHIFT),
105 ioaddr + DMA_BUS_MODE);
106
107 /* Mask interrupts by writing to CSR7 */
108 writel(DMA_INTR_DEFAULT_MASK, ioaddr + DMA_INTR_ENA);
109
110 /* The base address of the RX/TX descriptor lists must be written into
111 * DMA CSR3 and CSR4, respectively. */
112 writel(dma_tx, ioaddr + DMA_TX_BASE_ADDR);
113 writel(dma_rx, ioaddr + DMA_RCV_BASE_ADDR);
114
115 return 0;
116}
117
118/* Store and Forward capability is not used at all..
119 * The transmit threshold can be programmed by
120 * setting the TTC bits in the DMA control register.*/
121static void mac100_dma_operation_mode(unsigned long ioaddr, int txmode,
122 int rxmode)
123{
124 u32 csr6 = readl(ioaddr + DMA_CONTROL);
125
126 if (txmode <= 32)
127 csr6 |= DMA_CONTROL_TTC_32;
128 else if (txmode <= 64)
129 csr6 |= DMA_CONTROL_TTC_64;
130 else
131 csr6 |= DMA_CONTROL_TTC_128;
132
133 writel(csr6, ioaddr + DMA_CONTROL);
134
135 return;
136}
137
138static void mac100_dump_dma_regs(unsigned long ioaddr)
139{
140 int i;
141
142 DBG(KERN_DEBUG "MAC100 DMA CSR \n");
143 for (i = 0; i < 9; i++)
144 pr_debug("\t CSR%d (offset 0x%x): 0x%08x\n", i,
145 (DMA_BUS_MODE + i * 4),
146 readl(ioaddr + DMA_BUS_MODE + i * 4));
147 DBG(KERN_DEBUG "\t CSR20 (offset 0x%x): 0x%08x\n",
148 DMA_CUR_TX_BUF_ADDR, readl(ioaddr + DMA_CUR_TX_BUF_ADDR));
149 DBG(KERN_DEBUG "\t CSR21 (offset 0x%x): 0x%08x\n",
150 DMA_CUR_RX_BUF_ADDR, readl(ioaddr + DMA_CUR_RX_BUF_ADDR));
151 return;
152}
153
154/* DMA controller has two counters to track the number of
155 the receive missed frames. */
156static void mac100_dma_diagnostic_fr(void *data, struct stmmac_extra_stats *x,
157 unsigned long ioaddr)
158{
159 struct net_device_stats *stats = (struct net_device_stats *)data;
160 u32 csr8 = readl(ioaddr + DMA_MISSED_FRAME_CTR);
161
162 if (unlikely(csr8)) {
163 if (csr8 & DMA_MISSED_FRAME_OVE) {
164 stats->rx_over_errors += 0x800;
165 x->rx_overflow_cntr += 0x800;
166 } else {
167 unsigned int ove_cntr;
168 ove_cntr = ((csr8 & DMA_MISSED_FRAME_OVE_CNTR) >> 17);
169 stats->rx_over_errors += ove_cntr;
170 x->rx_overflow_cntr += ove_cntr;
171 }
172
173 if (csr8 & DMA_MISSED_FRAME_OVE_M) {
174 stats->rx_missed_errors += 0xffff;
175 x->rx_missed_cntr += 0xffff;
176 } else {
177 unsigned int miss_f = (csr8 & DMA_MISSED_FRAME_M_CNTR);
178 stats->rx_missed_errors += miss_f;
179 x->rx_missed_cntr += miss_f;
180 }
181 }
182 return;
183}
184
185static int mac100_get_tx_frame_status(void *data, struct stmmac_extra_stats *x,
186 struct dma_desc *p, unsigned long ioaddr)
187{
188 int ret = 0;
189 struct net_device_stats *stats = (struct net_device_stats *)data;
190
191 if (unlikely(p->des01.tx.error_summary)) {
192 if (unlikely(p->des01.tx.underflow_error)) {
193 x->tx_underflow++;
194 stats->tx_fifo_errors++;
195 }
196 if (unlikely(p->des01.tx.no_carrier)) {
197 x->tx_carrier++;
198 stats->tx_carrier_errors++;
199 }
200 if (unlikely(p->des01.tx.loss_carrier)) {
201 x->tx_losscarrier++;
202 stats->tx_carrier_errors++;
203 }
204 if (unlikely((p->des01.tx.excessive_deferral) ||
205 (p->des01.tx.excessive_collisions) ||
206 (p->des01.tx.late_collision)))
207 stats->collisions += p->des01.tx.collision_count;
208 ret = -1;
209 }
210 if (unlikely(p->des01.tx.heartbeat_fail)) {
211 x->tx_heartbeat++;
212 stats->tx_heartbeat_errors++;
213 ret = -1;
214 }
215 if (unlikely(p->des01.tx.deferred))
216 x->tx_deferred++;
217
218 return ret;
219}
220
221static int mac100_get_tx_len(struct dma_desc *p)
222{
223 return p->des01.tx.buffer1_size;
224}
225
226/* This function verifies if each incoming frame has some errors
227 * and, if required, updates the multicast statistics.
228 * In case of success, it returns csum_none becasue the device
229 * is not able to compute the csum in HW. */
230static int mac100_get_rx_frame_status(void *data, struct stmmac_extra_stats *x,
231 struct dma_desc *p)
232{
233 int ret = csum_none;
234 struct net_device_stats *stats = (struct net_device_stats *)data;
235
236 if (unlikely(p->des01.rx.last_descriptor == 0)) {
237 pr_warning("mac100 Error: Oversized Ethernet "
238 "frame spanned multiple buffers\n");
239 stats->rx_length_errors++;
240 return discard_frame;
241 }
242
243 if (unlikely(p->des01.rx.error_summary)) {
244 if (unlikely(p->des01.rx.descriptor_error))
245 x->rx_desc++;
246 if (unlikely(p->des01.rx.partial_frame_error))
247 x->rx_partial++;
248 if (unlikely(p->des01.rx.run_frame))
249 x->rx_runt++;
250 if (unlikely(p->des01.rx.frame_too_long))
251 x->rx_toolong++;
252 if (unlikely(p->des01.rx.collision)) {
253 x->rx_collision++;
254 stats->collisions++;
255 }
256 if (unlikely(p->des01.rx.crc_error)) {
257 x->rx_crc++;
258 stats->rx_crc_errors++;
259 }
260 ret = discard_frame;
261 }
262 if (unlikely(p->des01.rx.dribbling))
263 ret = discard_frame;
264
265 if (unlikely(p->des01.rx.length_error)) {
266 x->rx_lenght++;
267 ret = discard_frame;
268 }
269 if (unlikely(p->des01.rx.mii_error)) {
270 x->rx_mii++;
271 ret = discard_frame;
272 }
273 if (p->des01.rx.multicast_frame) {
274 x->rx_multicast++;
275 stats->multicast++;
276 }
277 return ret;
278}
279
280static void mac100_irq_status(unsigned long ioaddr)
281{
282 return;
283}
284
285static void mac100_set_umac_addr(unsigned long ioaddr, unsigned char *addr,
286 unsigned int reg_n)
287{
288 stmmac_set_mac_addr(ioaddr, addr, MAC_ADDR_HIGH, MAC_ADDR_LOW);
289}
290
291static void mac100_get_umac_addr(unsigned long ioaddr, unsigned char *addr,
292 unsigned int reg_n)
293{
294 stmmac_get_mac_addr(ioaddr, addr, MAC_ADDR_HIGH, MAC_ADDR_LOW);
295}
296
297static void mac100_set_filter(struct net_device *dev)
298{
299 unsigned long ioaddr = dev->base_addr;
300 u32 value = readl(ioaddr + MAC_CONTROL);
301
302 if (dev->flags & IFF_PROMISC) {
303 value |= MAC_CONTROL_PR;
304 value &= ~(MAC_CONTROL_PM | MAC_CONTROL_IF | MAC_CONTROL_HO |
305 MAC_CONTROL_HP);
306 } else if ((dev->mc_count > HASH_TABLE_SIZE)
307 || (dev->flags & IFF_ALLMULTI)) {
308 value |= MAC_CONTROL_PM;
309 value &= ~(MAC_CONTROL_PR | MAC_CONTROL_IF | MAC_CONTROL_HO);
310 writel(0xffffffff, ioaddr + MAC_HASH_HIGH);
311 writel(0xffffffff, ioaddr + MAC_HASH_LOW);
312 } else if (dev->mc_count == 0) { /* no multicast */
313 value &= ~(MAC_CONTROL_PM | MAC_CONTROL_PR | MAC_CONTROL_IF |
314 MAC_CONTROL_HO | MAC_CONTROL_HP);
315 } else {
316 int i;
317 u32 mc_filter[2];
318 struct dev_mc_list *mclist;
319
320 /* Perfect filter mode for physical address and Hash
321 filter for multicast */
322 value |= MAC_CONTROL_HP;
323 value &= ~(MAC_CONTROL_PM | MAC_CONTROL_PR | MAC_CONTROL_IF
324 | MAC_CONTROL_HO);
325
326 memset(mc_filter, 0, sizeof(mc_filter));
327 for (i = 0, mclist = dev->mc_list;
328 mclist && i < dev->mc_count; i++, mclist = mclist->next) {
329 /* The upper 6 bits of the calculated CRC are used to
330 * index the contens of the hash table */
331 int bit_nr =
332 ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26;
333 /* The most significant bit determines the register to
334 * use (H/L) while the other 5 bits determine the bit
335 * within the register. */
336 mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31);
337 }
338 writel(mc_filter[0], ioaddr + MAC_HASH_LOW);
339 writel(mc_filter[1], ioaddr + MAC_HASH_HIGH);
340 }
341
342 writel(value, ioaddr + MAC_CONTROL);
343
344 DBG(KERN_INFO "%s: CTRL reg: 0x%08x Hash regs: "
345 "HI 0x%08x, LO 0x%08x\n",
346 __func__, readl(ioaddr + MAC_CONTROL),
347 readl(ioaddr + MAC_HASH_HIGH), readl(ioaddr + MAC_HASH_LOW));
348 return;
349}
350
351static void mac100_flow_ctrl(unsigned long ioaddr, unsigned int duplex,
352 unsigned int fc, unsigned int pause_time)
353{
354 unsigned int flow = MAC_FLOW_CTRL_ENABLE;
355
356 if (duplex)
357 flow |= (pause_time << MAC_FLOW_CTRL_PT_SHIFT);
358 writel(flow, ioaddr + MAC_FLOW_CTRL);
359
360 return;
361}
362
363/* No PMT module supported in our SoC for the Ethernet Controller. */
364static void mac100_pmt(unsigned long ioaddr, unsigned long mode)
365{
366 return;
367}
368
369static void mac100_init_rx_desc(struct dma_desc *p, unsigned int ring_size,
370 int disable_rx_ic)
371{
372 int i;
373 for (i = 0; i < ring_size; i++) {
374 p->des01.rx.own = 1;
375 p->des01.rx.buffer1_size = BUF_SIZE_2KiB - 1;
376 if (i == ring_size - 1)
377 p->des01.rx.end_ring = 1;
378 if (disable_rx_ic)
379 p->des01.rx.disable_ic = 1;
380 p++;
381 }
382 return;
383}
384
385static void mac100_init_tx_desc(struct dma_desc *p, unsigned int ring_size)
386{
387 int i;
388 for (i = 0; i < ring_size; i++) {
389 p->des01.tx.own = 0;
390 if (i == ring_size - 1)
391 p->des01.tx.end_ring = 1;
392 p++;
393 }
394 return;
395}
396
397static int mac100_get_tx_owner(struct dma_desc *p)
398{
399 return p->des01.tx.own;
400}
401
402static int mac100_get_rx_owner(struct dma_desc *p)
403{
404 return p->des01.rx.own;
405}
406
407static void mac100_set_tx_owner(struct dma_desc *p)
408{
409 p->des01.tx.own = 1;
410}
411
412static void mac100_set_rx_owner(struct dma_desc *p)
413{
414 p->des01.rx.own = 1;
415}
416
417static int mac100_get_tx_ls(struct dma_desc *p)
418{
419 return p->des01.tx.last_segment;
420}
421
422static void mac100_release_tx_desc(struct dma_desc *p)
423{
424 int ter = p->des01.tx.end_ring;
425
426 /* clean field used within the xmit */
427 p->des01.tx.first_segment = 0;
428 p->des01.tx.last_segment = 0;
429 p->des01.tx.buffer1_size = 0;
430
431 /* clean status reported */
432 p->des01.tx.error_summary = 0;
433 p->des01.tx.underflow_error = 0;
434 p->des01.tx.no_carrier = 0;
435 p->des01.tx.loss_carrier = 0;
436 p->des01.tx.excessive_deferral = 0;
437 p->des01.tx.excessive_collisions = 0;
438 p->des01.tx.late_collision = 0;
439 p->des01.tx.heartbeat_fail = 0;
440 p->des01.tx.deferred = 0;
441
442 /* set termination field */
443 p->des01.tx.end_ring = ter;
444
445 return;
446}
447
448static void mac100_prepare_tx_desc(struct dma_desc *p, int is_fs, int len,
449 int csum_flag)
450{
451 p->des01.tx.first_segment = is_fs;
452 p->des01.tx.buffer1_size = len;
453}
454
455static void mac100_clear_tx_ic(struct dma_desc *p)
456{
457 p->des01.tx.interrupt = 0;
458}
459
460static void mac100_close_tx_desc(struct dma_desc *p)
461{
462 p->des01.tx.last_segment = 1;
463 p->des01.tx.interrupt = 1;
464}
465
466static int mac100_get_rx_frame_len(struct dma_desc *p)
467{
468 return p->des01.rx.frame_length;
469}
470
db98a0b0 471struct stmmac_ops mac100_ops = {
47dd7a54 472 .core_init = mac100_core_init,
db98a0b0
GC
473 .dump_regs = mac100_dump_mac_regs,
474 .host_irq_status = mac100_irq_status,
475 .set_filter = mac100_set_filter,
476 .flow_ctrl = mac100_flow_ctrl,
477 .pmt = mac100_pmt,
478 .set_umac_addr = mac100_set_umac_addr,
479 .get_umac_addr = mac100_get_umac_addr,
480};
481
482struct stmmac_dma_ops mac100_dma_ops = {
483 .init = mac100_dma_init,
484 .dump_regs = mac100_dump_dma_regs,
47dd7a54
GC
485 .dma_mode = mac100_dma_operation_mode,
486 .dma_diagnostic_fr = mac100_dma_diagnostic_fr,
aec7ff27
GC
487 .enable_dma_transmission = dwmac_enable_dma_transmission,
488 .enable_dma_irq = dwmac_enable_dma_irq,
489 .disable_dma_irq = dwmac_disable_dma_irq,
490 .start_tx = dwmac_dma_start_tx,
491 .stop_tx = dwmac_dma_stop_tx,
492 .start_rx = dwmac_dma_start_rx,
493 .stop_rx = dwmac_dma_stop_rx,
494 .dma_interrupt = dwmac_dma_interrupt,
db98a0b0
GC
495};
496
497struct stmmac_desc_ops mac100_desc_ops = {
47dd7a54
GC
498 .tx_status = mac100_get_tx_frame_status,
499 .rx_status = mac100_get_rx_frame_status,
500 .get_tx_len = mac100_get_tx_len,
47dd7a54
GC
501 .init_rx_desc = mac100_init_rx_desc,
502 .init_tx_desc = mac100_init_tx_desc,
503 .get_tx_owner = mac100_get_tx_owner,
504 .get_rx_owner = mac100_get_rx_owner,
505 .release_tx_desc = mac100_release_tx_desc,
506 .prepare_tx_desc = mac100_prepare_tx_desc,
507 .clear_tx_ic = mac100_clear_tx_ic,
508 .close_tx_desc = mac100_close_tx_desc,
509 .get_tx_ls = mac100_get_tx_ls,
510 .set_tx_owner = mac100_set_tx_owner,
511 .set_rx_owner = mac100_set_rx_owner,
512 .get_rx_frame_len = mac100_get_rx_frame_len,
47dd7a54
GC
513};
514
515struct mac_device_info *mac100_setup(unsigned long ioaddr)
516{
517 struct mac_device_info *mac;
518
519 mac = kzalloc(sizeof(const struct mac_device_info), GFP_KERNEL);
520
521 pr_info("\tMAC 10/100\n");
522
db98a0b0
GC
523 mac->mac = &mac100_ops;
524 mac->desc = &mac100_desc_ops;
525 mac->dma = &mac100_dma_ops;
526
527 mac->pmt = PMT_NOT_SUPPORTED;
528 mac->link.port = MAC_CONTROL_PS;
529 mac->link.duplex = MAC_CONTROL_F;
530 mac->link.speed = 0;
531 mac->mii.addr = MAC_MII_ADDR;
532 mac->mii.data = MAC_MII_DATA;
47dd7a54
GC
533
534 return mac;
535}