]> bbs.cooldavid.org Git - net-next-2.6.git/blob - drivers/net/stmmac/dwmac1000_core.c
f9c7c1cbda93967a5c594f466482ae9cf1a45910
[net-next-2.6.git] / drivers / net / stmmac / dwmac1000_core.c
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 <linux/slab.h>
31 #include "dwmac1000.h"
32
33 static void dwmac1000_core_init(unsigned long ioaddr)
34 {
35         u32 value = readl(ioaddr + GMAC_CONTROL);
36         value |= GMAC_CORE_INIT;
37         writel(value, ioaddr + GMAC_CONTROL);
38
39         /* STBus Bridge Configuration */
40         /*writel(0xc5608, ioaddr + 0x00007000);*/
41
42         /* Freeze MMC counters */
43         writel(0x8, ioaddr + GMAC_MMC_CTRL);
44         /* Mask GMAC interrupts */
45         writel(0x207, ioaddr + GMAC_INT_MASK);
46
47 #ifdef STMMAC_VLAN_TAG_USED
48         /* Tag detection without filtering */
49         writel(0x0, ioaddr + GMAC_VLAN_TAG);
50 #endif
51         return;
52 }
53
54 static void dwmac1000_dump_regs(unsigned long ioaddr)
55 {
56         int i;
57         pr_info("\tDWMAC1000 regs (base addr = 0x%8x)\n", (unsigned int)ioaddr);
58
59         for (i = 0; i < 55; i++) {
60                 int offset = i * 4;
61                 pr_info("\tReg No. %d (offset 0x%x): 0x%08x\n", i,
62                         offset, readl(ioaddr + offset));
63         }
64         return;
65 }
66
67 static void dwmac1000_set_umac_addr(unsigned long ioaddr, unsigned char *addr,
68                                 unsigned int reg_n)
69 {
70         stmmac_set_mac_addr(ioaddr, addr, GMAC_ADDR_HIGH(reg_n),
71                                 GMAC_ADDR_LOW(reg_n));
72 }
73
74 static void dwmac1000_get_umac_addr(unsigned long ioaddr, unsigned char *addr,
75                                 unsigned int reg_n)
76 {
77         stmmac_get_mac_addr(ioaddr, addr, GMAC_ADDR_HIGH(reg_n),
78                                 GMAC_ADDR_LOW(reg_n));
79 }
80
81 static void dwmac1000_set_filter(struct net_device *dev)
82 {
83         unsigned long ioaddr = dev->base_addr;
84         unsigned int value = 0;
85
86         DBG(KERN_INFO "%s: # mcasts %d, # unicast %d\n",
87             __func__, netdev_mc_count(dev), netdev_uc_count(dev));
88
89         if (dev->flags & IFF_PROMISC)
90                 value = GMAC_FRAME_FILTER_PR;
91         else if ((netdev_mc_count(dev) > HASH_TABLE_SIZE)
92                    || (dev->flags & IFF_ALLMULTI)) {
93                 value = GMAC_FRAME_FILTER_PM;   /* pass all multi */
94                 writel(0xffffffff, ioaddr + GMAC_HASH_HIGH);
95                 writel(0xffffffff, ioaddr + GMAC_HASH_LOW);
96         } else if (!netdev_mc_empty(dev)) {
97                 u32 mc_filter[2];
98                 struct netdev_hw_addr *ha;
99
100                 /* Hash filter for multicast */
101                 value = GMAC_FRAME_FILTER_HMC;
102
103                 memset(mc_filter, 0, sizeof(mc_filter));
104                 netdev_for_each_mc_addr(ha, dev) {
105                         /* The upper 6 bits of the calculated CRC are used to
106                            index the contens of the hash table */
107                         int bit_nr =
108                             bitrev32(~crc32_le(~0, ha->addr, 6)) >> 26;
109                         /* The most significant bit determines the register to
110                          * use (H/L) while the other 5 bits determine the bit
111                          * within the register. */
112                         mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31);
113                 }
114                 writel(mc_filter[0], ioaddr + GMAC_HASH_LOW);
115                 writel(mc_filter[1], ioaddr + GMAC_HASH_HIGH);
116         }
117
118         /* Handle multiple unicast addresses (perfect filtering)*/
119         if (netdev_uc_count(dev) > GMAC_MAX_UNICAST_ADDRESSES)
120                 /* Switch to promiscuous mode is more than 16 addrs
121                    are required */
122                 value |= GMAC_FRAME_FILTER_PR;
123         else {
124                 int reg = 1;
125                 struct netdev_hw_addr *ha;
126
127                 netdev_for_each_uc_addr(ha, dev) {
128                         dwmac1000_set_umac_addr(ioaddr, ha->addr, reg);
129                         reg++;
130                 }
131         }
132
133 #ifdef FRAME_FILTER_DEBUG
134         /* Enable Receive all mode (to debug filtering_fail errors) */
135         value |= GMAC_FRAME_FILTER_RA;
136 #endif
137         writel(value, ioaddr + GMAC_FRAME_FILTER);
138
139         DBG(KERN_INFO "\tFrame Filter reg: 0x%08x\n\tHash regs: "
140             "HI 0x%08x, LO 0x%08x\n", readl(ioaddr + GMAC_FRAME_FILTER),
141             readl(ioaddr + GMAC_HASH_HIGH), readl(ioaddr + GMAC_HASH_LOW));
142
143         return;
144 }
145
146 static void dwmac1000_flow_ctrl(unsigned long ioaddr, unsigned int duplex,
147                            unsigned int fc, unsigned int pause_time)
148 {
149         unsigned int flow = 0;
150
151         DBG(KERN_DEBUG "GMAC Flow-Control:\n");
152         if (fc & FLOW_RX) {
153                 DBG(KERN_DEBUG "\tReceive Flow-Control ON\n");
154                 flow |= GMAC_FLOW_CTRL_RFE;
155         }
156         if (fc & FLOW_TX) {
157                 DBG(KERN_DEBUG "\tTransmit Flow-Control ON\n");
158                 flow |= GMAC_FLOW_CTRL_TFE;
159         }
160
161         if (duplex) {
162                 DBG(KERN_DEBUG "\tduplex mode: pause time: %d\n", pause_time);
163                 flow |= (pause_time << GMAC_FLOW_CTRL_PT_SHIFT);
164         }
165
166         writel(flow, ioaddr + GMAC_FLOW_CTRL);
167         return;
168 }
169
170 static void dwmac1000_pmt(unsigned long ioaddr, unsigned long mode)
171 {
172         unsigned int pmt = 0;
173
174         if (mode == WAKE_MAGIC) {
175                 DBG(KERN_DEBUG "GMAC: WOL Magic frame\n");
176                 pmt |= power_down | magic_pkt_en;
177         } else if (mode == WAKE_UCAST) {
178                 DBG(KERN_DEBUG "GMAC: WOL on global unicast\n");
179                 pmt |= global_unicast;
180         }
181
182         writel(pmt, ioaddr + GMAC_PMT);
183         return;
184 }
185
186
187 static void dwmac1000_irq_status(unsigned long ioaddr)
188 {
189         u32 intr_status = readl(ioaddr + GMAC_INT_STATUS);
190
191         /* Not used events (e.g. MMC interrupts) are not handled. */
192         if ((intr_status & mmc_tx_irq))
193                 DBG(KERN_DEBUG "GMAC: MMC tx interrupt: 0x%08x\n",
194                     readl(ioaddr + GMAC_MMC_TX_INTR));
195         if (unlikely(intr_status & mmc_rx_irq))
196                 DBG(KERN_DEBUG "GMAC: MMC rx interrupt: 0x%08x\n",
197                     readl(ioaddr + GMAC_MMC_RX_INTR));
198         if (unlikely(intr_status & mmc_rx_csum_offload_irq))
199                 DBG(KERN_DEBUG "GMAC: MMC rx csum offload: 0x%08x\n",
200                     readl(ioaddr + GMAC_MMC_RX_CSUM_OFFLOAD));
201         if (unlikely(intr_status & pmt_irq)) {
202                 DBG(KERN_DEBUG "GMAC: received Magic frame\n");
203                 /* clear the PMT bits 5 and 6 by reading the PMT
204                  * status register. */
205                 readl(ioaddr + GMAC_PMT);
206         }
207
208         return;
209 }
210
211 struct stmmac_ops dwmac1000_ops = {
212         .core_init = dwmac1000_core_init,
213         .dump_regs = dwmac1000_dump_regs,
214         .host_irq_status = dwmac1000_irq_status,
215         .set_filter = dwmac1000_set_filter,
216         .flow_ctrl = dwmac1000_flow_ctrl,
217         .pmt = dwmac1000_pmt,
218         .set_umac_addr = dwmac1000_set_umac_addr,
219         .get_umac_addr = dwmac1000_get_umac_addr,
220 };
221
222 struct mac_device_info *dwmac1000_setup(unsigned long ioaddr)
223 {
224         struct mac_device_info *mac;
225         u32 uid = readl(ioaddr + GMAC_VERSION);
226
227         pr_info("\tDWMAC1000 - user ID: 0x%x, Synopsys ID: 0x%x\n",
228                 ((uid & 0x0000ff00) >> 8), (uid & 0x000000ff));
229
230         mac = kzalloc(sizeof(const struct mac_device_info), GFP_KERNEL);
231
232         mac->mac = &dwmac1000_ops;
233         mac->desc = &dwmac1000_desc_ops;
234         mac->dma = &dwmac1000_dma_ops;
235
236         mac->pmt = PMT_SUPPORTED;
237         mac->link.port = GMAC_CONTROL_PS;
238         mac->link.duplex = GMAC_CONTROL_DM;
239         mac->link.speed = GMAC_CONTROL_FES;
240         mac->mii.addr = GMAC_MII_ADDR;
241         mac->mii.data = GMAC_MII_DATA;
242
243         return mac;
244 }