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.
5 DWC Ether MAC 10/100 Universal version 4.0 has been used for developing
8 Copyright (C) 2007-2009 STMicroelectronics Ltd
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.
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
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.
23 The full GNU General Public License is included in this distribution in
24 the file called "COPYING".
26 Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
27 *******************************************************************************/
29 #include <linux/crc32.h>
30 #include <linux/mii.h>
31 #include <linux/phy.h>
32 #include <linux/slab.h>
36 #include "dwmac_dma.h"
39 /*#define DWMAC100_DEBUG*/
41 #define DBG(fmt, args...) printk(fmt, ## args)
43 #define DBG(fmt, args...) do { } while (0)
46 static void dwmac100_core_init(unsigned long ioaddr)
48 u32 value = readl(ioaddr + MAC_CONTROL);
50 writel((value | MAC_CORE_INIT), ioaddr + MAC_CONTROL);
52 #ifdef STMMAC_VLAN_TAG_USED
53 writel(ETH_P_8021Q, ioaddr + MAC_VLAN1);
58 static void dwmac100_dump_mac_regs(unsigned long ioaddr)
60 pr_info("\t----------------------------------------------\n"
61 "\t DWMAC 100 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));
94 static int dwmac100_dma_init(unsigned long ioaddr, int pbl, u32 dma_tx,
97 u32 value = readl(ioaddr + DMA_BUS_MODE);
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));
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);
107 /* Mask interrupts by writing to CSR7 */
108 writel(DMA_INTR_DEFAULT_MASK, ioaddr + DMA_INTR_ENA);
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);
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.*/
121 static void dwmac100_dma_operation_mode(unsigned long ioaddr, int txmode,
124 u32 csr6 = readl(ioaddr + DMA_CONTROL);
127 csr6 |= DMA_CONTROL_TTC_32;
128 else if (txmode <= 64)
129 csr6 |= DMA_CONTROL_TTC_64;
131 csr6 |= DMA_CONTROL_TTC_128;
133 writel(csr6, ioaddr + DMA_CONTROL);
138 static void dwmac100_dump_dma_regs(unsigned long ioaddr)
142 DBG(KERN_DEBUG "DWMAC 100 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));
154 /* DMA controller has two counters to track the number of
155 * the receive missed frames. */
156 static void dwmac100_dma_diagnostic_fr(void *data,
157 struct stmmac_extra_stats *x,
158 unsigned long ioaddr)
160 struct net_device_stats *stats = (struct net_device_stats *)data;
161 u32 csr8 = readl(ioaddr + DMA_MISSED_FRAME_CTR);
163 if (unlikely(csr8)) {
164 if (csr8 & DMA_MISSED_FRAME_OVE) {
165 stats->rx_over_errors += 0x800;
166 x->rx_overflow_cntr += 0x800;
168 unsigned int ove_cntr;
169 ove_cntr = ((csr8 & DMA_MISSED_FRAME_OVE_CNTR) >> 17);
170 stats->rx_over_errors += ove_cntr;
171 x->rx_overflow_cntr += ove_cntr;
174 if (csr8 & DMA_MISSED_FRAME_OVE_M) {
175 stats->rx_missed_errors += 0xffff;
176 x->rx_missed_cntr += 0xffff;
178 unsigned int miss_f = (csr8 & DMA_MISSED_FRAME_M_CNTR);
179 stats->rx_missed_errors += miss_f;
180 x->rx_missed_cntr += miss_f;
186 static int dwmac100_get_tx_frame_status(void *data,
187 struct stmmac_extra_stats *x,
188 struct dma_desc *p, unsigned long ioaddr)
191 struct net_device_stats *stats = (struct net_device_stats *)data;
193 if (unlikely(p->des01.tx.error_summary)) {
194 if (unlikely(p->des01.tx.underflow_error)) {
196 stats->tx_fifo_errors++;
198 if (unlikely(p->des01.tx.no_carrier)) {
200 stats->tx_carrier_errors++;
202 if (unlikely(p->des01.tx.loss_carrier)) {
204 stats->tx_carrier_errors++;
206 if (unlikely((p->des01.tx.excessive_deferral) ||
207 (p->des01.tx.excessive_collisions) ||
208 (p->des01.tx.late_collision)))
209 stats->collisions += p->des01.tx.collision_count;
212 if (unlikely(p->des01.tx.heartbeat_fail)) {
214 stats->tx_heartbeat_errors++;
217 if (unlikely(p->des01.tx.deferred))
223 static int dwmac100_get_tx_len(struct dma_desc *p)
225 return p->des01.tx.buffer1_size;
228 /* This function verifies if each incoming frame has some errors
229 * and, if required, updates the multicast statistics.
230 * In case of success, it returns csum_none becasue the device
231 * is not able to compute the csum in HW. */
232 static int dwmac100_get_rx_frame_status(void *data,
233 struct stmmac_extra_stats *x,
237 struct net_device_stats *stats = (struct net_device_stats *)data;
239 if (unlikely(p->des01.rx.last_descriptor == 0)) {
240 pr_warning("dwmac100 Error: Oversized Ethernet "
241 "frame spanned multiple buffers\n");
242 stats->rx_length_errors++;
243 return discard_frame;
246 if (unlikely(p->des01.rx.error_summary)) {
247 if (unlikely(p->des01.rx.descriptor_error))
249 if (unlikely(p->des01.rx.partial_frame_error))
251 if (unlikely(p->des01.rx.run_frame))
253 if (unlikely(p->des01.rx.frame_too_long))
255 if (unlikely(p->des01.rx.collision)) {
259 if (unlikely(p->des01.rx.crc_error)) {
261 stats->rx_crc_errors++;
265 if (unlikely(p->des01.rx.dribbling))
268 if (unlikely(p->des01.rx.length_error)) {
272 if (unlikely(p->des01.rx.mii_error)) {
276 if (p->des01.rx.multicast_frame) {
283 static void dwmac100_irq_status(unsigned long ioaddr)
288 static void dwmac100_set_umac_addr(unsigned long ioaddr, unsigned char *addr,
291 stmmac_set_mac_addr(ioaddr, addr, MAC_ADDR_HIGH, MAC_ADDR_LOW);
294 static void dwmac100_get_umac_addr(unsigned long ioaddr, unsigned char *addr,
297 stmmac_get_mac_addr(ioaddr, addr, MAC_ADDR_HIGH, MAC_ADDR_LOW);
300 static void dwmac100_set_filter(struct net_device *dev)
302 unsigned long ioaddr = dev->base_addr;
303 u32 value = readl(ioaddr + MAC_CONTROL);
305 if (dev->flags & IFF_PROMISC) {
306 value |= MAC_CONTROL_PR;
307 value &= ~(MAC_CONTROL_PM | MAC_CONTROL_IF | MAC_CONTROL_HO |
309 } else if ((netdev_mc_count(dev) > HASH_TABLE_SIZE)
310 || (dev->flags & IFF_ALLMULTI)) {
311 value |= MAC_CONTROL_PM;
312 value &= ~(MAC_CONTROL_PR | MAC_CONTROL_IF | MAC_CONTROL_HO);
313 writel(0xffffffff, ioaddr + MAC_HASH_HIGH);
314 writel(0xffffffff, ioaddr + MAC_HASH_LOW);
315 } else if (netdev_mc_empty(dev)) { /* no multicast */
316 value &= ~(MAC_CONTROL_PM | MAC_CONTROL_PR | MAC_CONTROL_IF |
317 MAC_CONTROL_HO | MAC_CONTROL_HP);
320 struct dev_mc_list *mclist;
322 /* Perfect filter mode for physical address and Hash
323 filter for multicast */
324 value |= MAC_CONTROL_HP;
325 value &= ~(MAC_CONTROL_PM | MAC_CONTROL_PR |
326 MAC_CONTROL_IF | MAC_CONTROL_HO);
328 memset(mc_filter, 0, sizeof(mc_filter));
329 netdev_for_each_mc_addr(mclist, dev) {
330 /* The upper 6 bits of the calculated CRC are used to
331 * index the contens of the hash table */
333 ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26;
334 /* The most significant bit determines the register to
335 * use (H/L) while the other 5 bits determine the bit
336 * within the register. */
337 mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31);
339 writel(mc_filter[0], ioaddr + MAC_HASH_LOW);
340 writel(mc_filter[1], ioaddr + MAC_HASH_HIGH);
343 writel(value, ioaddr + MAC_CONTROL);
345 DBG(KERN_INFO "%s: CTRL reg: 0x%08x Hash regs: "
346 "HI 0x%08x, LO 0x%08x\n",
347 __func__, readl(ioaddr + MAC_CONTROL),
348 readl(ioaddr + MAC_HASH_HIGH), readl(ioaddr + MAC_HASH_LOW));
352 static void dwmac100_flow_ctrl(unsigned long ioaddr, unsigned int duplex,
353 unsigned int fc, unsigned int pause_time)
355 unsigned int flow = MAC_FLOW_CTRL_ENABLE;
358 flow |= (pause_time << MAC_FLOW_CTRL_PT_SHIFT);
359 writel(flow, ioaddr + MAC_FLOW_CTRL);
364 /* No PMT module supported for this Ethernet Controller.
365 * Tested on ST platforms only.
367 static void dwmac100_pmt(unsigned long ioaddr, unsigned long mode)
372 static void dwmac100_init_rx_desc(struct dma_desc *p, unsigned int ring_size,
376 for (i = 0; i < ring_size; i++) {
378 p->des01.rx.buffer1_size = BUF_SIZE_2KiB - 1;
379 if (i == ring_size - 1)
380 p->des01.rx.end_ring = 1;
382 p->des01.rx.disable_ic = 1;
388 static void dwmac100_init_tx_desc(struct dma_desc *p, unsigned int ring_size)
391 for (i = 0; i < ring_size; i++) {
393 if (i == ring_size - 1)
394 p->des01.tx.end_ring = 1;
400 static int dwmac100_get_tx_owner(struct dma_desc *p)
402 return p->des01.tx.own;
405 static int dwmac100_get_rx_owner(struct dma_desc *p)
407 return p->des01.rx.own;
410 static void dwmac100_set_tx_owner(struct dma_desc *p)
415 static void dwmac100_set_rx_owner(struct dma_desc *p)
420 static int dwmac100_get_tx_ls(struct dma_desc *p)
422 return p->des01.tx.last_segment;
425 static void dwmac100_release_tx_desc(struct dma_desc *p)
427 int ter = p->des01.tx.end_ring;
429 /* clean field used within the xmit */
430 p->des01.tx.first_segment = 0;
431 p->des01.tx.last_segment = 0;
432 p->des01.tx.buffer1_size = 0;
434 /* clean status reported */
435 p->des01.tx.error_summary = 0;
436 p->des01.tx.underflow_error = 0;
437 p->des01.tx.no_carrier = 0;
438 p->des01.tx.loss_carrier = 0;
439 p->des01.tx.excessive_deferral = 0;
440 p->des01.tx.excessive_collisions = 0;
441 p->des01.tx.late_collision = 0;
442 p->des01.tx.heartbeat_fail = 0;
443 p->des01.tx.deferred = 0;
445 /* set termination field */
446 p->des01.tx.end_ring = ter;
451 static void dwmac100_prepare_tx_desc(struct dma_desc *p, int is_fs, int len,
454 p->des01.tx.first_segment = is_fs;
455 p->des01.tx.buffer1_size = len;
458 static void dwmac100_clear_tx_ic(struct dma_desc *p)
460 p->des01.tx.interrupt = 0;
463 static void dwmac100_close_tx_desc(struct dma_desc *p)
465 p->des01.tx.last_segment = 1;
466 p->des01.tx.interrupt = 1;
469 static int dwmac100_get_rx_frame_len(struct dma_desc *p)
471 return p->des01.rx.frame_length;
474 struct stmmac_ops dwmac100_ops = {
475 .core_init = dwmac100_core_init,
476 .dump_regs = dwmac100_dump_mac_regs,
477 .host_irq_status = dwmac100_irq_status,
478 .set_filter = dwmac100_set_filter,
479 .flow_ctrl = dwmac100_flow_ctrl,
481 .set_umac_addr = dwmac100_set_umac_addr,
482 .get_umac_addr = dwmac100_get_umac_addr,
485 struct stmmac_dma_ops dwmac100_dma_ops = {
486 .init = dwmac100_dma_init,
487 .dump_regs = dwmac100_dump_dma_regs,
488 .dma_mode = dwmac100_dma_operation_mode,
489 .dma_diagnostic_fr = dwmac100_dma_diagnostic_fr,
490 .enable_dma_transmission = dwmac_enable_dma_transmission,
491 .enable_dma_irq = dwmac_enable_dma_irq,
492 .disable_dma_irq = dwmac_disable_dma_irq,
493 .start_tx = dwmac_dma_start_tx,
494 .stop_tx = dwmac_dma_stop_tx,
495 .start_rx = dwmac_dma_start_rx,
496 .stop_rx = dwmac_dma_stop_rx,
497 .dma_interrupt = dwmac_dma_interrupt,
500 struct stmmac_desc_ops dwmac100_desc_ops = {
501 .tx_status = dwmac100_get_tx_frame_status,
502 .rx_status = dwmac100_get_rx_frame_status,
503 .get_tx_len = dwmac100_get_tx_len,
504 .init_rx_desc = dwmac100_init_rx_desc,
505 .init_tx_desc = dwmac100_init_tx_desc,
506 .get_tx_owner = dwmac100_get_tx_owner,
507 .get_rx_owner = dwmac100_get_rx_owner,
508 .release_tx_desc = dwmac100_release_tx_desc,
509 .prepare_tx_desc = dwmac100_prepare_tx_desc,
510 .clear_tx_ic = dwmac100_clear_tx_ic,
511 .close_tx_desc = dwmac100_close_tx_desc,
512 .get_tx_ls = dwmac100_get_tx_ls,
513 .set_tx_owner = dwmac100_set_tx_owner,
514 .set_rx_owner = dwmac100_set_rx_owner,
515 .get_rx_frame_len = dwmac100_get_rx_frame_len,
518 struct mac_device_info *dwmac100_setup(unsigned long ioaddr)
520 struct mac_device_info *mac;
522 mac = kzalloc(sizeof(const struct mac_device_info), GFP_KERNEL);
524 pr_info("\tDWMAC100\n");
526 mac->mac = &dwmac100_ops;
527 mac->desc = &dwmac100_desc_ops;
528 mac->dma = &dwmac100_dma_ops;
530 mac->pmt = PMT_NOT_SUPPORTED;
531 mac->link.port = MAC_CONTROL_PS;
532 mac->link.duplex = MAC_CONTROL_F;
534 mac->mii.addr = MAC_MII_ADDR;
535 mac->mii.data = MAC_MII_DATA;