Merge remote-tracking branches 'asoc/topic/intel', 'asoc/topic/kirkwood', 'asoc/topic...
[deliverable/linux.git] / drivers / net / ethernet / stmicro / 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>
e58bb43f 31#include <linux/ethtool.h>
b7f080cf 32#include <asm/io.h>
21d437cc
GC
33#include "dwmac1000.h"
34
2618abb7 35static void dwmac1000_core_init(void __iomem *ioaddr, int mtu)
21d437cc
GC
36{
37 u32 value = readl(ioaddr + GMAC_CONTROL);
38 value |= GMAC_CORE_INIT;
2618abb7
VB
39 if (mtu > 1500)
40 value |= GMAC_CONTROL_2K;
41 if (mtu > 2000)
42 value |= GMAC_CONTROL_JE;
43
21d437cc
GC
44 writel(value, ioaddr + GMAC_CONTROL);
45
21d437cc
GC
46 /* Mask GMAC interrupts */
47 writel(0x207, ioaddr + GMAC_INT_MASK);
48
49#ifdef STMMAC_VLAN_TAG_USED
50 /* Tag detection without filtering */
51 writel(0x0, ioaddr + GMAC_VLAN_TAG);
52#endif
21d437cc
GC
53}
54
38912bdb 55static int dwmac1000_rx_ipc_enable(void __iomem *ioaddr)
ebbb293f
GC
56{
57 u32 value = readl(ioaddr + GMAC_CONTROL);
58
59 value |= GMAC_CONTROL_IPC;
60 writel(value, ioaddr + GMAC_CONTROL);
61
62 value = readl(ioaddr + GMAC_CONTROL);
63
64 return !!(value & GMAC_CONTROL_IPC);
65}
66
ad01b7d4 67static void dwmac1000_dump_regs(void __iomem *ioaddr)
21d437cc
GC
68{
69 int i;
1f0f6388 70 pr_info("\tDWMAC1000 regs (base addr = 0x%p)\n", ioaddr);
21d437cc
GC
71
72 for (i = 0; i < 55; i++) {
73 int offset = i * 4;
74 pr_info("\tReg No. %d (offset 0x%x): 0x%08x\n", i,
75 offset, readl(ioaddr + offset));
76 }
21d437cc
GC
77}
78
ad01b7d4 79static void dwmac1000_set_umac_addr(void __iomem *ioaddr, unsigned char *addr,
ceb69499 80 unsigned int reg_n)
21d437cc
GC
81{
82 stmmac_set_mac_addr(ioaddr, addr, GMAC_ADDR_HIGH(reg_n),
ceb69499 83 GMAC_ADDR_LOW(reg_n));
21d437cc
GC
84}
85
ad01b7d4 86static void dwmac1000_get_umac_addr(void __iomem *ioaddr, unsigned char *addr,
ceb69499 87 unsigned int reg_n)
21d437cc
GC
88{
89 stmmac_get_mac_addr(ioaddr, addr, GMAC_ADDR_HIGH(reg_n),
ceb69499 90 GMAC_ADDR_LOW(reg_n));
21d437cc
GC
91}
92
cffb13f4 93static void dwmac1000_set_filter(struct net_device *dev, int id)
21d437cc 94{
ceb69499 95 void __iomem *ioaddr = (void __iomem *)dev->base_addr;
21d437cc 96 unsigned int value = 0;
cffb13f4 97 unsigned int perfect_addr_number;
21d437cc 98
83d7af64
GC
99 pr_debug("%s: # mcasts %d, # unicast %d\n", __func__,
100 netdev_mc_count(dev), netdev_uc_count(dev));
21d437cc
GC
101
102 if (dev->flags & IFF_PROMISC)
103 value = GMAC_FRAME_FILTER_PR;
4cd24eaf 104 else if ((netdev_mc_count(dev) > HASH_TABLE_SIZE)
ceb69499 105 || (dev->flags & IFF_ALLMULTI)) {
21d437cc
GC
106 value = GMAC_FRAME_FILTER_PM; /* pass all multi */
107 writel(0xffffffff, ioaddr + GMAC_HASH_HIGH);
108 writel(0xffffffff, ioaddr + GMAC_HASH_LOW);
4cd24eaf 109 } else if (!netdev_mc_empty(dev)) {
21d437cc 110 u32 mc_filter[2];
22bedad3 111 struct netdev_hw_addr *ha;
21d437cc
GC
112
113 /* Hash filter for multicast */
114 value = GMAC_FRAME_FILTER_HMC;
115
116 memset(mc_filter, 0, sizeof(mc_filter));
22bedad3 117 netdev_for_each_mc_addr(ha, dev) {
21d437cc 118 /* The upper 6 bits of the calculated CRC are used to
ceb69499
GC
119 * index the contens of the hash table
120 */
121 int bit_nr = bitrev32(~crc32_le(~0, ha->addr, 6)) >> 26;
21d437cc
GC
122 /* The most significant bit determines the register to
123 * use (H/L) while the other 5 bits determine the bit
ceb69499
GC
124 * within the register.
125 */
21d437cc
GC
126 mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31);
127 }
128 writel(mc_filter[0], ioaddr + GMAC_HASH_LOW);
129 writel(mc_filter[1], ioaddr + GMAC_HASH_HIGH);
130 }
131
cffb13f4
GC
132 /* Extra 16 regs are available in cores newer than the 3.40. */
133 if (id > DWMAC_CORE_3_40)
134 perfect_addr_number = GMAC_MAX_PERFECT_ADDRESSES;
135 else
136 perfect_addr_number = GMAC_MAX_PERFECT_ADDRESSES / 2;
137
ceb69499 138 /* Handle multiple unicast addresses (perfect filtering) */
cffb13f4 139 if (netdev_uc_count(dev) > perfect_addr_number)
ceb69499
GC
140 /* Switch to promiscuous mode if more than 16 addrs
141 * are required
142 */
21d437cc
GC
143 value |= GMAC_FRAME_FILTER_PR;
144 else {
145 int reg = 1;
146 struct netdev_hw_addr *ha;
147
32e7bfc4
JP
148 netdev_for_each_uc_addr(ha, dev) {
149 dwmac1000_set_umac_addr(ioaddr, ha->addr, reg);
150 reg++;
21d437cc
GC
151 }
152 }
153
154#ifdef FRAME_FILTER_DEBUG
155 /* Enable Receive all mode (to debug filtering_fail errors) */
156 value |= GMAC_FRAME_FILTER_RA;
157#endif
158 writel(value, ioaddr + GMAC_FRAME_FILTER);
159
83d7af64 160 pr_debug("\tFilter: 0x%08x\n\tHash: HI 0x%08x, LO 0x%08x\n",
ceb69499
GC
161 readl(ioaddr + GMAC_FRAME_FILTER),
162 readl(ioaddr + GMAC_HASH_HIGH), readl(ioaddr + GMAC_HASH_LOW));
21d437cc
GC
163}
164
ad01b7d4 165static void dwmac1000_flow_ctrl(void __iomem *ioaddr, unsigned int duplex,
ceb69499 166 unsigned int fc, unsigned int pause_time)
21d437cc
GC
167{
168 unsigned int flow = 0;
169
83d7af64 170 pr_debug("GMAC Flow-Control:\n");
21d437cc 171 if (fc & FLOW_RX) {
83d7af64 172 pr_debug("\tReceive Flow-Control ON\n");
21d437cc
GC
173 flow |= GMAC_FLOW_CTRL_RFE;
174 }
175 if (fc & FLOW_TX) {
83d7af64 176 pr_debug("\tTransmit Flow-Control ON\n");
21d437cc
GC
177 flow |= GMAC_FLOW_CTRL_TFE;
178 }
179
180 if (duplex) {
83d7af64 181 pr_debug("\tduplex mode: PAUSE %d\n", pause_time);
21d437cc
GC
182 flow |= (pause_time << GMAC_FLOW_CTRL_PT_SHIFT);
183 }
184
185 writel(flow, ioaddr + GMAC_FLOW_CTRL);
21d437cc
GC
186}
187
ad01b7d4 188static void dwmac1000_pmt(void __iomem *ioaddr, unsigned long mode)
21d437cc
GC
189{
190 unsigned int pmt = 0;
191
74ae2fd7 192 if (mode & WAKE_MAGIC) {
83d7af64 193 pr_debug("GMAC: WOL Magic frame\n");
21d437cc 194 pmt |= power_down | magic_pkt_en;
74ae2fd7
GC
195 }
196 if (mode & WAKE_UCAST) {
83d7af64 197 pr_debug("GMAC: WOL on global unicast\n");
21d437cc
GC
198 pmt |= global_unicast;
199 }
200
201 writel(pmt, ioaddr + GMAC_PMT);
21d437cc
GC
202}
203
0982a0f6
GC
204static int dwmac1000_irq_status(void __iomem *ioaddr,
205 struct stmmac_extra_stats *x)
21d437cc
GC
206{
207 u32 intr_status = readl(ioaddr + GMAC_INT_STATUS);
0982a0f6 208 int ret = 0;
21d437cc
GC
209
210 /* Not used events (e.g. MMC interrupts) are not handled. */
83d7af64 211 if ((intr_status & mmc_tx_irq))
0982a0f6 212 x->mmc_tx_irq_n++;
83d7af64 213 if (unlikely(intr_status & mmc_rx_irq))
0982a0f6 214 x->mmc_rx_irq_n++;
83d7af64 215 if (unlikely(intr_status & mmc_rx_csum_offload_irq))
0982a0f6 216 x->mmc_rx_csum_offload_irq_n++;
21d437cc 217 if (unlikely(intr_status & pmt_irq)) {
ceb69499 218 /* clear the PMT bits 5 and 6 by reading the PMT status reg */
21d437cc 219 readl(ioaddr + GMAC_PMT);
0982a0f6 220 x->irq_receive_pmt_irq_n++;
21d437cc 221 }
d765955d
GC
222 /* MAC trx/rx EEE LPI entry/exit interrupts */
223 if (intr_status & lpiis_irq) {
224 /* Clean LPI interrupt by reading the Reg 12 */
0982a0f6 225 ret = readl(ioaddr + LPI_CTRL_STATUS);
d765955d 226
83d7af64 227 if (ret & LPI_CTRL_STATUS_TLPIEN)
0982a0f6 228 x->irq_tx_path_in_lpi_mode_n++;
83d7af64 229 if (ret & LPI_CTRL_STATUS_TLPIEX)
0982a0f6 230 x->irq_tx_path_exit_lpi_mode_n++;
83d7af64 231 if (ret & LPI_CTRL_STATUS_RLPIEN)
0982a0f6 232 x->irq_rx_path_in_lpi_mode_n++;
83d7af64 233 if (ret & LPI_CTRL_STATUS_RLPIEX)
0982a0f6 234 x->irq_rx_path_exit_lpi_mode_n++;
d765955d
GC
235 }
236
0982a0f6 237 if ((intr_status & pcs_ane_irq) || (intr_status & pcs_link_irq)) {
0982a0f6
GC
238 readl(ioaddr + GMAC_AN_STATUS);
239 x->irq_pcs_ane_n++;
240 }
241 if (intr_status & rgmii_irq) {
ceb69499 242 u32 status = readl(ioaddr + GMAC_S_R_GMII);
0982a0f6 243 x->irq_rgmii_n++;
e58bb43f
GC
244
245 /* Save and dump the link status. */
246 if (status & GMAC_S_R_GMII_LINK) {
247 int speed_value = (status & GMAC_S_R_GMII_SPEED) >>
ceb69499 248 GMAC_S_R_GMII_SPEED_SHIFT;
e58bb43f
GC
249 x->pcs_duplex = (status & GMAC_S_R_GMII_MODE);
250
251 if (speed_value == GMAC_S_R_GMII_SPEED_125)
252 x->pcs_speed = SPEED_1000;
253 else if (speed_value == GMAC_S_R_GMII_SPEED_25)
254 x->pcs_speed = SPEED_100;
255 else
256 x->pcs_speed = SPEED_10;
257
258 x->pcs_link = 1;
83d7af64
GC
259 pr_debug("%s: Link is Up - %d/%s\n", __func__,
260 (int)x->pcs_speed,
e58bb43f
GC
261 x->pcs_duplex ? "Full" : "Half");
262 } else {
263 x->pcs_link = 0;
83d7af64 264 pr_debug("%s: Link is Down\n", __func__);
e58bb43f 265 }
0982a0f6
GC
266 }
267
268 return ret;
d765955d
GC
269}
270
ceb69499 271static void dwmac1000_set_eee_mode(void __iomem *ioaddr)
d765955d
GC
272{
273 u32 value;
274
275 /* Enable the link status receive on RGMII, SGMII ore SMII
276 * receive path and instruct the transmit to enter in LPI
ceb69499
GC
277 * state.
278 */
d765955d
GC
279 value = readl(ioaddr + LPI_CTRL_STATUS);
280 value |= LPI_CTRL_STATUS_LPIEN | LPI_CTRL_STATUS_LPITXA;
281 writel(value, ioaddr + LPI_CTRL_STATUS);
282}
283
ceb69499 284static void dwmac1000_reset_eee_mode(void __iomem *ioaddr)
d765955d
GC
285{
286 u32 value;
287
288 value = readl(ioaddr + LPI_CTRL_STATUS);
289 value &= ~(LPI_CTRL_STATUS_LPIEN | LPI_CTRL_STATUS_LPITXA);
290 writel(value, ioaddr + LPI_CTRL_STATUS);
291}
292
ceb69499 293static void dwmac1000_set_eee_pls(void __iomem *ioaddr, int link)
d765955d
GC
294{
295 u32 value;
296
297 value = readl(ioaddr + LPI_CTRL_STATUS);
298
299 if (link)
300 value |= LPI_CTRL_STATUS_PLS;
301 else
302 value &= ~LPI_CTRL_STATUS_PLS;
303
304 writel(value, ioaddr + LPI_CTRL_STATUS);
305}
306
ceb69499 307static void dwmac1000_set_eee_timer(void __iomem *ioaddr, int ls, int tw)
d765955d
GC
308{
309 int value = ((tw & 0xffff)) | ((ls & 0x7ff) << 16);
310
311 /* Program the timers in the LPI timer control register:
312 * LS: minimum time (ms) for which the link
313 * status from PHY should be ok before transmitting
314 * the LPI pattern.
315 * TW: minimum time (us) for which the core waits
316 * after it has stopped transmitting the LPI pattern.
317 */
318 writel(value, ioaddr + LPI_TIMER_CTRL);
21d437cc
GC
319}
320
e58bb43f
GC
321static void dwmac1000_ctrl_ane(void __iomem *ioaddr, bool restart)
322{
e58bb43f 323 /* auto negotiation enable and External Loopback enable */
c8df8ce3 324 u32 value = GMAC_AN_CTRL_ANE | GMAC_AN_CTRL_ELE;
e58bb43f
GC
325
326 if (restart)
327 value |= GMAC_AN_CTRL_RAN;
328
329 writel(value, ioaddr + GMAC_AN_CTRL);
330}
331
332static void dwmac1000_get_adv(void __iomem *ioaddr, struct rgmii_adv *adv)
333{
334 u32 value = readl(ioaddr + GMAC_ANE_ADV);
335
336 if (value & GMAC_ANE_FD)
337 adv->duplex = DUPLEX_FULL;
338 if (value & GMAC_ANE_HD)
339 adv->duplex |= DUPLEX_HALF;
340
341 adv->pause = (value & GMAC_ANE_PSE) >> GMAC_ANE_PSE_SHIFT;
342
343 value = readl(ioaddr + GMAC_ANE_LPA);
344
345 if (value & GMAC_ANE_FD)
346 adv->lp_duplex = DUPLEX_FULL;
347 if (value & GMAC_ANE_HD)
348 adv->lp_duplex = DUPLEX_HALF;
349
350 adv->lp_pause = (value & GMAC_ANE_PSE) >> GMAC_ANE_PSE_SHIFT;
351}
352
cadb7924 353static const struct stmmac_ops dwmac1000_ops = {
21d437cc 354 .core_init = dwmac1000_core_init,
38912bdb 355 .rx_ipc = dwmac1000_rx_ipc_enable,
21d437cc
GC
356 .dump_regs = dwmac1000_dump_regs,
357 .host_irq_status = dwmac1000_irq_status,
358 .set_filter = dwmac1000_set_filter,
359 .flow_ctrl = dwmac1000_flow_ctrl,
360 .pmt = dwmac1000_pmt,
361 .set_umac_addr = dwmac1000_set_umac_addr,
362 .get_umac_addr = dwmac1000_get_umac_addr,
ceb69499
GC
363 .set_eee_mode = dwmac1000_set_eee_mode,
364 .reset_eee_mode = dwmac1000_reset_eee_mode,
365 .set_eee_timer = dwmac1000_set_eee_timer,
366 .set_eee_pls = dwmac1000_set_eee_pls,
e58bb43f
GC
367 .ctrl_ane = dwmac1000_ctrl_ane,
368 .get_adv = dwmac1000_get_adv,
21d437cc
GC
369};
370
ad01b7d4 371struct mac_device_info *dwmac1000_setup(void __iomem *ioaddr)
21d437cc
GC
372{
373 struct mac_device_info *mac;
f0b9d786 374 u32 hwid = readl(ioaddr + GMAC_VERSION);
21d437cc
GC
375
376 mac = kzalloc(sizeof(const struct mac_device_info), GFP_KERNEL);
1ff21906
DC
377 if (!mac)
378 return NULL;
21d437cc
GC
379
380 mac->mac = &dwmac1000_ops;
21d437cc
GC
381 mac->dma = &dwmac1000_dma_ops;
382
21d437cc
GC
383 mac->link.port = GMAC_CONTROL_PS;
384 mac->link.duplex = GMAC_CONTROL_DM;
385 mac->link.speed = GMAC_CONTROL_FES;
386 mac->mii.addr = GMAC_MII_ADDR;
387 mac->mii.data = GMAC_MII_DATA;
f0b9d786 388 mac->synopsys_uid = hwid;
21d437cc
GC
389
390 return mac;
391}
This page took 0.447946 seconds and 5 git commands to generate.