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