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