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