blob: b943f5ddd8fd68b9cdd8ebd5893bf9f10bdd9de1 [file] [log] [blame]
Christoph Lameter8199d3a2005-03-30 13:34:31 -08001/*****************************************************************************
2 * *
3 * File: pm3393.c *
Scott Bardone559fb512005-06-23 01:40:19 -04004 * $Revision: 1.16 $ *
5 * $Date: 2005/05/14 00:59:32 $ *
Christoph Lameter8199d3a2005-03-30 13:34:31 -08006 * Description: *
7 * PMC/SIERRA (pm3393) MAC-PHY functionality. *
8 * part of the Chelsio 10Gb Ethernet Driver. *
9 * *
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License, version 2, as *
12 * published by the Free Software Foundation. *
13 * *
14 * You should have received a copy of the GNU General Public License along *
15 * with this program; if not, write to the Free Software Foundation, Inc., *
16 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
17 * *
18 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED *
19 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF *
20 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. *
21 * *
22 * http://www.chelsio.com *
23 * *
24 * Copyright (c) 2003 - 2005 Chelsio Communications, Inc. *
25 * All rights reserved. *
26 * *
27 * Maintainers: maintainers@chelsio.com *
28 * *
29 * Authors: Dimitrios Michailidis <dm@chelsio.com> *
30 * Tina Yang <tainay@chelsio.com> *
31 * Felix Marti <felix@chelsio.com> *
32 * Scott Bardone <sbardone@chelsio.com> *
33 * Kurt Ottaway <kottaway@chelsio.com> *
34 * Frank DiMambro <frank@chelsio.com> *
35 * *
36 * History: *
37 * *
38 ****************************************************************************/
39
40#include "common.h"
41#include "regs.h"
42#include "gmac.h"
43#include "elmer0.h"
44#include "suni1x10gexp_regs.h"
45
46/* 802.3ae 10Gb/s MDIO Manageable Device(MMD)
47 */
Scott Bardone559fb512005-06-23 01:40:19 -040048enum {
Stephen Hemminger11e5a202006-12-01 16:36:13 -080049 MMD_RESERVED,
50 MMD_PMAPMD,
51 MMD_WIS,
52 MMD_PCS,
53 MMD_PHY_XGXS, /* XGMII Extender Sublayer */
54 MMD_DTE_XGXS,
Scott Bardone559fb512005-06-23 01:40:19 -040055};
Christoph Lameter8199d3a2005-03-30 13:34:31 -080056
Scott Bardone559fb512005-06-23 01:40:19 -040057enum {
Stephen Hemminger11e5a202006-12-01 16:36:13 -080058 PHY_XGXS_CTRL_1,
59 PHY_XGXS_STATUS_1
Scott Bardone559fb512005-06-23 01:40:19 -040060};
Christoph Lameter8199d3a2005-03-30 13:34:31 -080061
62#define OFFSET(REG_ADDR) (REG_ADDR << 2)
63
64/* Max frame size PM3393 can handle. Includes Ethernet header and CRC. */
65#define MAX_FRAME_SIZE 9600
66
67#define IPG 12
68#define TXXG_CONF1_VAL ((IPG << SUNI1x10GEXP_BITOFF_TXXG_IPGT) | \
69 SUNI1x10GEXP_BITMSK_TXXG_32BIT_ALIGN | SUNI1x10GEXP_BITMSK_TXXG_CRCEN | \
70 SUNI1x10GEXP_BITMSK_TXXG_PADEN)
71#define RXXG_CONF1_VAL (SUNI1x10GEXP_BITMSK_RXXG_PUREP | 0x14 | \
72 SUNI1x10GEXP_BITMSK_RXXG_FLCHK | SUNI1x10GEXP_BITMSK_RXXG_CRC_STRIP)
73
74/* Update statistics every 15 minutes */
75#define STATS_TICK_SECS (15 * 60)
76
77enum { /* RMON registers */
78 RxOctetsReceivedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_1_LOW,
79 RxUnicastFramesReceivedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_4_LOW,
80 RxMulticastFramesReceivedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_5_LOW,
81 RxBroadcastFramesReceivedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_6_LOW,
82 RxPAUSEMACCtrlFramesReceived = SUNI1x10GEXP_REG_MSTAT_COUNTER_8_LOW,
83 RxFrameCheckSequenceErrors = SUNI1x10GEXP_REG_MSTAT_COUNTER_10_LOW,
84 RxFramesLostDueToInternalMACErrors = SUNI1x10GEXP_REG_MSTAT_COUNTER_11_LOW,
85 RxSymbolErrors = SUNI1x10GEXP_REG_MSTAT_COUNTER_12_LOW,
86 RxInRangeLengthErrors = SUNI1x10GEXP_REG_MSTAT_COUNTER_13_LOW,
87 RxFramesTooLongErrors = SUNI1x10GEXP_REG_MSTAT_COUNTER_15_LOW,
88 RxJabbers = SUNI1x10GEXP_REG_MSTAT_COUNTER_16_LOW,
89 RxFragments = SUNI1x10GEXP_REG_MSTAT_COUNTER_17_LOW,
90 RxUndersizedFrames = SUNI1x10GEXP_REG_MSTAT_COUNTER_18_LOW,
Stephen Hemmingerf1d3d382006-12-01 16:36:16 -080091 RxJumboFramesReceivedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_25_LOW,
92 RxJumboOctetsReceivedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_26_LOW,
Christoph Lameter8199d3a2005-03-30 13:34:31 -080093
94 TxOctetsTransmittedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_33_LOW,
95 TxFramesLostDueToInternalMACTransmissionError = SUNI1x10GEXP_REG_MSTAT_COUNTER_35_LOW,
96 TxTransmitSystemError = SUNI1x10GEXP_REG_MSTAT_COUNTER_36_LOW,
97 TxUnicastFramesTransmittedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_38_LOW,
98 TxMulticastFramesTransmittedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_40_LOW,
99 TxBroadcastFramesTransmittedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_42_LOW,
Stephen Hemmingerf1d3d382006-12-01 16:36:16 -0800100 TxPAUSEMACCtrlFramesTransmitted = SUNI1x10GEXP_REG_MSTAT_COUNTER_43_LOW,
101 TxJumboFramesReceivedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_51_LOW,
102 TxJumboOctetsReceivedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_52_LOW
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800103};
104
105struct _cmac_instance {
106 u8 enabled;
107 u8 fc;
108 u8 mac_addr[6];
109};
110
111static int pmread(struct cmac *cmac, u32 reg, u32 * data32)
112{
113 t1_tpi_read(cmac->adapter, OFFSET(reg), data32);
114 return 0;
115}
116
117static int pmwrite(struct cmac *cmac, u32 reg, u32 data32)
118{
119 t1_tpi_write(cmac->adapter, OFFSET(reg), data32);
120 return 0;
121}
122
123/* Port reset. */
124static int pm3393_reset(struct cmac *cmac)
125{
126 return 0;
127}
128
129/*
130 * Enable interrupts for the PM3393
131
132 1. Enable PM3393 BLOCK interrupts.
133 2. Enable PM3393 Master Interrupt bit(INTE)
134 3. Enable ELMER's PM3393 bit.
135 4. Enable Terminator external interrupt.
136*/
137static int pm3393_interrupt_enable(struct cmac *cmac)
138{
139 u32 pl_intr;
140
141 /* PM3393 - Enabling all hardware block interrupts.
142 */
143 pmwrite(cmac, SUNI1x10GEXP_REG_SERDES_3125_INTERRUPT_ENABLE, 0xffff);
144 pmwrite(cmac, SUNI1x10GEXP_REG_XRF_INTERRUPT_ENABLE, 0xffff);
145 pmwrite(cmac, SUNI1x10GEXP_REG_XRF_DIAG_INTERRUPT_ENABLE, 0xffff);
146 pmwrite(cmac, SUNI1x10GEXP_REG_RXOAM_INTERRUPT_ENABLE, 0xffff);
147
148 /* Don't interrupt on statistics overflow, we are polling */
149 pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_0, 0);
150 pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_1, 0);
151 pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_2, 0);
152 pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_3, 0);
153
154 pmwrite(cmac, SUNI1x10GEXP_REG_IFLX_FIFO_OVERFLOW_ENABLE, 0xffff);
155 pmwrite(cmac, SUNI1x10GEXP_REG_PL4ODP_INTERRUPT_MASK, 0xffff);
156 pmwrite(cmac, SUNI1x10GEXP_REG_XTEF_INTERRUPT_ENABLE, 0xffff);
157 pmwrite(cmac, SUNI1x10GEXP_REG_TXOAM_INTERRUPT_ENABLE, 0xffff);
158 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_CONFIG_3, 0xffff);
159 pmwrite(cmac, SUNI1x10GEXP_REG_PL4IO_LOCK_DETECT_MASK, 0xffff);
160 pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_CONFIG_3, 0xffff);
161 pmwrite(cmac, SUNI1x10GEXP_REG_PL4IDU_INTERRUPT_MASK, 0xffff);
162 pmwrite(cmac, SUNI1x10GEXP_REG_EFLX_FIFO_OVERFLOW_ERROR_ENABLE, 0xffff);
163
164 /* PM3393 - Global interrupt enable
165 */
166 /* TBD XXX Disable for now until we figure out why error interrupts keep asserting. */
167 pmwrite(cmac, SUNI1x10GEXP_REG_GLOBAL_INTERRUPT_ENABLE,
168 0 /*SUNI1x10GEXP_BITMSK_TOP_INTE */ );
169
170 /* TERMINATOR - PL_INTERUPTS_EXT */
Scott Bardone559fb512005-06-23 01:40:19 -0400171 pl_intr = readl(cmac->adapter->regs + A_PL_ENABLE);
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800172 pl_intr |= F_PL_INTR_EXT;
Scott Bardone559fb512005-06-23 01:40:19 -0400173 writel(pl_intr, cmac->adapter->regs + A_PL_ENABLE);
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800174 return 0;
175}
176
177static int pm3393_interrupt_disable(struct cmac *cmac)
178{
179 u32 elmer;
180
181 /* PM3393 - Enabling HW interrupt blocks. */
182 pmwrite(cmac, SUNI1x10GEXP_REG_SERDES_3125_INTERRUPT_ENABLE, 0);
183 pmwrite(cmac, SUNI1x10GEXP_REG_XRF_INTERRUPT_ENABLE, 0);
184 pmwrite(cmac, SUNI1x10GEXP_REG_XRF_DIAG_INTERRUPT_ENABLE, 0);
185 pmwrite(cmac, SUNI1x10GEXP_REG_RXOAM_INTERRUPT_ENABLE, 0);
186 pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_0, 0);
187 pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_1, 0);
188 pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_2, 0);
189 pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_3, 0);
190 pmwrite(cmac, SUNI1x10GEXP_REG_IFLX_FIFO_OVERFLOW_ENABLE, 0);
191 pmwrite(cmac, SUNI1x10GEXP_REG_PL4ODP_INTERRUPT_MASK, 0);
192 pmwrite(cmac, SUNI1x10GEXP_REG_XTEF_INTERRUPT_ENABLE, 0);
193 pmwrite(cmac, SUNI1x10GEXP_REG_TXOAM_INTERRUPT_ENABLE, 0);
194 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_CONFIG_3, 0);
195 pmwrite(cmac, SUNI1x10GEXP_REG_PL4IO_LOCK_DETECT_MASK, 0);
196 pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_CONFIG_3, 0);
197 pmwrite(cmac, SUNI1x10GEXP_REG_PL4IDU_INTERRUPT_MASK, 0);
198 pmwrite(cmac, SUNI1x10GEXP_REG_EFLX_FIFO_OVERFLOW_ERROR_ENABLE, 0);
199
200 /* PM3393 - Global interrupt enable */
201 pmwrite(cmac, SUNI1x10GEXP_REG_GLOBAL_INTERRUPT_ENABLE, 0);
202
203 /* ELMER - External chip interrupts. */
204 t1_tpi_read(cmac->adapter, A_ELMER0_INT_ENABLE, &elmer);
205 elmer &= ~ELMER0_GP_BIT1;
206 t1_tpi_write(cmac->adapter, A_ELMER0_INT_ENABLE, elmer);
207
208 /* TERMINATOR - PL_INTERUPTS_EXT */
209 /* DO NOT DISABLE TERMINATOR's EXTERNAL INTERRUPTS. ANOTHER CHIP
210 * COULD WANT THEM ENABLED. We disable PM3393 at the ELMER level.
211 */
212
213 return 0;
214}
215
216static int pm3393_interrupt_clear(struct cmac *cmac)
217{
218 u32 elmer;
219 u32 pl_intr;
220 u32 val32;
221
222 /* PM3393 - Clearing HW interrupt blocks. Note, this assumes
223 * bit WCIMODE=0 for a clear-on-read.
224 */
225 pmread(cmac, SUNI1x10GEXP_REG_SERDES_3125_INTERRUPT_STATUS, &val32);
226 pmread(cmac, SUNI1x10GEXP_REG_XRF_INTERRUPT_STATUS, &val32);
227 pmread(cmac, SUNI1x10GEXP_REG_XRF_DIAG_INTERRUPT_STATUS, &val32);
228 pmread(cmac, SUNI1x10GEXP_REG_RXOAM_INTERRUPT_STATUS, &val32);
229 pmread(cmac, SUNI1x10GEXP_REG_PL4ODP_INTERRUPT, &val32);
230 pmread(cmac, SUNI1x10GEXP_REG_XTEF_INTERRUPT_STATUS, &val32);
231 pmread(cmac, SUNI1x10GEXP_REG_IFLX_FIFO_OVERFLOW_INTERRUPT, &val32);
232 pmread(cmac, SUNI1x10GEXP_REG_TXOAM_INTERRUPT_STATUS, &val32);
233 pmread(cmac, SUNI1x10GEXP_REG_RXXG_INTERRUPT, &val32);
234 pmread(cmac, SUNI1x10GEXP_REG_TXXG_INTERRUPT, &val32);
235 pmread(cmac, SUNI1x10GEXP_REG_PL4IDU_INTERRUPT, &val32);
236 pmread(cmac, SUNI1x10GEXP_REG_EFLX_FIFO_OVERFLOW_ERROR_INDICATION,
237 &val32);
238 pmread(cmac, SUNI1x10GEXP_REG_PL4IO_LOCK_DETECT_STATUS, &val32);
239 pmread(cmac, SUNI1x10GEXP_REG_PL4IO_LOCK_DETECT_CHANGE, &val32);
240
241 /* PM3393 - Global interrupt status
242 */
243 pmread(cmac, SUNI1x10GEXP_REG_MASTER_INTERRUPT_STATUS, &val32);
244
245 /* ELMER - External chip interrupts.
246 */
247 t1_tpi_read(cmac->adapter, A_ELMER0_INT_CAUSE, &elmer);
248 elmer |= ELMER0_GP_BIT1;
249 t1_tpi_write(cmac->adapter, A_ELMER0_INT_CAUSE, elmer);
250
251 /* TERMINATOR - PL_INTERUPTS_EXT
252 */
Scott Bardone559fb512005-06-23 01:40:19 -0400253 pl_intr = readl(cmac->adapter->regs + A_PL_CAUSE);
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800254 pl_intr |= F_PL_INTR_EXT;
Scott Bardone559fb512005-06-23 01:40:19 -0400255 writel(pl_intr, cmac->adapter->regs + A_PL_CAUSE);
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800256
257 return 0;
258}
259
260/* Interrupt handler */
261static int pm3393_interrupt_handler(struct cmac *cmac)
262{
263 u32 master_intr_status;
264/*
265 1. Read master interrupt register.
266 2. Read BLOCK's interrupt status registers.
267 3. Handle BLOCK interrupts.
268*/
269 /* Read the master interrupt status register. */
270 pmread(cmac, SUNI1x10GEXP_REG_MASTER_INTERRUPT_STATUS,
271 &master_intr_status);
Stephen Hemmingerf1d3d382006-12-01 16:36:16 -0800272 CH_DBG(cmac->adapter, INTR, "PM3393 intr cause 0x%x\n",
273 master_intr_status);
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800274
275 /* TBD XXX Lets just clear everything for now */
276 pm3393_interrupt_clear(cmac);
277
278 return 0;
279}
280
281static int pm3393_enable(struct cmac *cmac, int which)
282{
283 if (which & MAC_DIRECTION_RX)
284 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_CONFIG_1,
285 (RXXG_CONF1_VAL | SUNI1x10GEXP_BITMSK_RXXG_RXEN));
286
287 if (which & MAC_DIRECTION_TX) {
288 u32 val = TXXG_CONF1_VAL | SUNI1x10GEXP_BITMSK_TXXG_TXEN0;
289
290 if (cmac->instance->fc & PAUSE_RX)
291 val |= SUNI1x10GEXP_BITMSK_TXXG_FCRX;
292 if (cmac->instance->fc & PAUSE_TX)
293 val |= SUNI1x10GEXP_BITMSK_TXXG_FCTX;
294 pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_CONFIG_1, val);
295 }
296
297 cmac->instance->enabled |= which;
298 return 0;
299}
300
301static int pm3393_enable_port(struct cmac *cmac, int which)
302{
303 /* Clear port statistics */
304 pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_CONTROL,
305 SUNI1x10GEXP_BITMSK_MSTAT_CLEAR);
306 udelay(2);
307 memset(&cmac->stats, 0, sizeof(struct cmac_statistics));
308
309 pm3393_enable(cmac, which);
310
311 /*
312 * XXX This should be done by the PHY and preferrably not at all.
313 * The PHY doesn't give us link status indication on its own so have
314 * the link management code query it instead.
315 */
Stephen Hemmingerf1d3d382006-12-01 16:36:16 -0800316 t1_link_changed(cmac->adapter, 0);
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800317 return 0;
318}
319
320static int pm3393_disable(struct cmac *cmac, int which)
321{
322 if (which & MAC_DIRECTION_RX)
323 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_CONFIG_1, RXXG_CONF1_VAL);
324 if (which & MAC_DIRECTION_TX)
325 pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_CONFIG_1, TXXG_CONF1_VAL);
326
327 /*
328 * The disable is graceful. Give the PM3393 time. Can't wait very
329 * long here, we may be holding locks.
330 */
331 udelay(20);
332
333 cmac->instance->enabled &= ~which;
334 return 0;
335}
336
337static int pm3393_loopback_enable(struct cmac *cmac)
338{
339 return 0;
340}
341
342static int pm3393_loopback_disable(struct cmac *cmac)
343{
344 return 0;
345}
346
347static int pm3393_set_mtu(struct cmac *cmac, int mtu)
348{
349 int enabled = cmac->instance->enabled;
350
351 /* MAX_FRAME_SIZE includes header + FCS, mtu doesn't */
352 mtu += 14 + 4;
353 if (mtu > MAX_FRAME_SIZE)
354 return -EINVAL;
355
356 /* Disable Rx/Tx MAC before configuring it. */
357 if (enabled)
358 pm3393_disable(cmac, MAC_DIRECTION_RX | MAC_DIRECTION_TX);
359
360 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MAX_FRAME_LENGTH, mtu);
361 pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_MAX_FRAME_SIZE, mtu);
362
363 if (enabled)
364 pm3393_enable(cmac, enabled);
365 return 0;
366}
367
368static u32 calc_crc(u8 *b, int len)
369{
370 int i;
371 u32 crc = (u32)~0;
372
373 /* calculate crc one bit at a time */
374 while (len--) {
375 crc ^= *b++;
376 for (i = 0; i < 8; i++) {
377 if (crc & 0x1)
378 crc = (crc >> 1) ^ 0xedb88320;
379 else
380 crc = (crc >> 1);
381 }
382 }
383
384 /* reverse bits */
385 crc = ((crc >> 4) & 0x0f0f0f0f) | ((crc << 4) & 0xf0f0f0f0);
386 crc = ((crc >> 2) & 0x33333333) | ((crc << 2) & 0xcccccccc);
387 crc = ((crc >> 1) & 0x55555555) | ((crc << 1) & 0xaaaaaaaa);
388 /* swap bytes */
389 crc = (crc >> 16) | (crc << 16);
390 crc = (crc >> 8 & 0x00ff00ff) | (crc << 8 & 0xff00ff00);
391
392 return crc;
393}
394
395static int pm3393_set_rx_mode(struct cmac *cmac, struct t1_rx_mode *rm)
396{
397 int enabled = cmac->instance->enabled & MAC_DIRECTION_RX;
398 u32 rx_mode;
399
400 /* Disable MAC RX before reconfiguring it */
401 if (enabled)
402 pm3393_disable(cmac, MAC_DIRECTION_RX);
403
404 pmread(cmac, SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_2, &rx_mode);
405 rx_mode &= ~(SUNI1x10GEXP_BITMSK_RXXG_PMODE |
406 SUNI1x10GEXP_BITMSK_RXXG_MHASH_EN);
407 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_2,
408 (u16)rx_mode);
409
410 if (t1_rx_mode_promisc(rm)) {
411 /* Promiscuous mode. */
412 rx_mode |= SUNI1x10GEXP_BITMSK_RXXG_PMODE;
413 }
414 if (t1_rx_mode_allmulti(rm)) {
415 /* Accept all multicast. */
416 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_LOW, 0xffff);
417 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_MIDLOW, 0xffff);
418 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_MIDHIGH, 0xffff);
419 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_HIGH, 0xffff);
420 rx_mode |= SUNI1x10GEXP_BITMSK_RXXG_MHASH_EN;
421 } else if (t1_rx_mode_mc_cnt(rm)) {
422 /* Accept one or more multicast(s). */
423 u8 *addr;
424 int bit;
425 u16 mc_filter[4] = { 0, };
426
427 while ((addr = t1_get_next_mcaddr(rm))) {
428 bit = (calc_crc(addr, ETH_ALEN) >> 23) & 0x3f; /* bit[23:28] */
429 mc_filter[bit >> 4] |= 1 << (bit & 0xf);
430 }
431 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_LOW, mc_filter[0]);
432 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_MIDLOW, mc_filter[1]);
433 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_MIDHIGH, mc_filter[2]);
434 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_HIGH, mc_filter[3]);
435 rx_mode |= SUNI1x10GEXP_BITMSK_RXXG_MHASH_EN;
436 }
437
438 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_2, (u16)rx_mode);
439
440 if (enabled)
441 pm3393_enable(cmac, MAC_DIRECTION_RX);
442
443 return 0;
444}
445
446static int pm3393_get_speed_duplex_fc(struct cmac *cmac, int *speed,
447 int *duplex, int *fc)
448{
449 if (speed)
450 *speed = SPEED_10000;
451 if (duplex)
452 *duplex = DUPLEX_FULL;
453 if (fc)
454 *fc = cmac->instance->fc;
455 return 0;
456}
457
458static int pm3393_set_speed_duplex_fc(struct cmac *cmac, int speed, int duplex,
459 int fc)
460{
461 if (speed >= 0 && speed != SPEED_10000)
462 return -1;
463 if (duplex >= 0 && duplex != DUPLEX_FULL)
464 return -1;
465 if (fc & ~(PAUSE_TX | PAUSE_RX))
466 return -1;
467
468 if (fc != cmac->instance->fc) {
469 cmac->instance->fc = (u8) fc;
470 if (cmac->instance->enabled & MAC_DIRECTION_TX)
471 pm3393_enable(cmac, MAC_DIRECTION_TX);
472 }
473 return 0;
474}
475
476#define RMON_UPDATE(mac, name, stat_name) \
477 { \
478 t1_tpi_read((mac)->adapter, OFFSET(name), &val0); \
479 t1_tpi_read((mac)->adapter, OFFSET(((name)+1)), &val1); \
480 t1_tpi_read((mac)->adapter, OFFSET(((name)+2)), &val2); \
481 (mac)->stats.stat_name = ((u64)val0 & 0xffff) | \
482 (((u64)val1 & 0xffff) << 16) | \
483 (((u64)val2 & 0xff) << 32) | \
484 ((mac)->stats.stat_name & \
485 (~(u64)0 << 40)); \
486 if (ro & \
487 ((name - SUNI1x10GEXP_REG_MSTAT_COUNTER_0_LOW) >> 2)) \
488 (mac)->stats.stat_name += ((u64)1 << 40); \
489 }
490
491static const struct cmac_statistics *pm3393_update_statistics(struct cmac *mac,
492 int flag)
493{
494 u64 ro;
495 u32 val0, val1, val2, val3;
496
497 /* Snap the counters */
498 pmwrite(mac, SUNI1x10GEXP_REG_MSTAT_CONTROL,
499 SUNI1x10GEXP_BITMSK_MSTAT_SNAP);
500
501 /* Counter rollover, clear on read */
502 pmread(mac, SUNI1x10GEXP_REG_MSTAT_COUNTER_ROLLOVER_0, &val0);
503 pmread(mac, SUNI1x10GEXP_REG_MSTAT_COUNTER_ROLLOVER_1, &val1);
504 pmread(mac, SUNI1x10GEXP_REG_MSTAT_COUNTER_ROLLOVER_2, &val2);
505 pmread(mac, SUNI1x10GEXP_REG_MSTAT_COUNTER_ROLLOVER_3, &val3);
506 ro = ((u64)val0 & 0xffff) | (((u64)val1 & 0xffff) << 16) |
507 (((u64)val2 & 0xffff) << 32) | (((u64)val3 & 0xffff) << 48);
508
509 /* Rx stats */
510 RMON_UPDATE(mac, RxOctetsReceivedOK, RxOctetsOK);
511 RMON_UPDATE(mac, RxUnicastFramesReceivedOK, RxUnicastFramesOK);
512 RMON_UPDATE(mac, RxMulticastFramesReceivedOK, RxMulticastFramesOK);
513 RMON_UPDATE(mac, RxBroadcastFramesReceivedOK, RxBroadcastFramesOK);
514 RMON_UPDATE(mac, RxPAUSEMACCtrlFramesReceived, RxPauseFrames);
515 RMON_UPDATE(mac, RxFrameCheckSequenceErrors, RxFCSErrors);
516 RMON_UPDATE(mac, RxFramesLostDueToInternalMACErrors,
517 RxInternalMACRcvError);
518 RMON_UPDATE(mac, RxSymbolErrors, RxSymbolErrors);
519 RMON_UPDATE(mac, RxInRangeLengthErrors, RxInRangeLengthErrors);
520 RMON_UPDATE(mac, RxFramesTooLongErrors , RxFrameTooLongErrors);
521 RMON_UPDATE(mac, RxJabbers, RxJabberErrors);
522 RMON_UPDATE(mac, RxFragments, RxRuntErrors);
523 RMON_UPDATE(mac, RxUndersizedFrames, RxRuntErrors);
Stephen Hemmingerf1d3d382006-12-01 16:36:16 -0800524 RMON_UPDATE(mac, RxJumboFramesReceivedOK, RxJumboFramesOK);
525 RMON_UPDATE(mac, RxJumboOctetsReceivedOK, RxJumboOctetsOK);
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800526
527 /* Tx stats */
528 RMON_UPDATE(mac, TxOctetsTransmittedOK, TxOctetsOK);
529 RMON_UPDATE(mac, TxFramesLostDueToInternalMACTransmissionError,
530 TxInternalMACXmitError);
531 RMON_UPDATE(mac, TxTransmitSystemError, TxFCSErrors);
532 RMON_UPDATE(mac, TxUnicastFramesTransmittedOK, TxUnicastFramesOK);
533 RMON_UPDATE(mac, TxMulticastFramesTransmittedOK, TxMulticastFramesOK);
534 RMON_UPDATE(mac, TxBroadcastFramesTransmittedOK, TxBroadcastFramesOK);
535 RMON_UPDATE(mac, TxPAUSEMACCtrlFramesTransmitted, TxPauseFrames);
Stephen Hemmingerf1d3d382006-12-01 16:36:16 -0800536 RMON_UPDATE(mac, TxJumboFramesReceivedOK, TxJumboFramesOK);
537 RMON_UPDATE(mac, TxJumboOctetsReceivedOK, TxJumboOctetsOK);
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800538
539 return &mac->stats;
540}
541
542static int pm3393_macaddress_get(struct cmac *cmac, u8 mac_addr[6])
543{
544 memcpy(mac_addr, cmac->instance->mac_addr, 6);
545 return 0;
546}
547
548static int pm3393_macaddress_set(struct cmac *cmac, u8 ma[6])
549{
550 u32 val, lo, mid, hi, enabled = cmac->instance->enabled;
551
552 /*
553 * MAC addr: 00:07:43:00:13:09
554 *
555 * ma[5] = 0x09
556 * ma[4] = 0x13
557 * ma[3] = 0x00
558 * ma[2] = 0x43
559 * ma[1] = 0x07
560 * ma[0] = 0x00
561 *
562 * The PM3393 requires byte swapping and reverse order entry
563 * when programming MAC addresses:
564 *
565 * low_bits[15:0] = ma[1]:ma[0]
566 * mid_bits[31:16] = ma[3]:ma[2]
567 * high_bits[47:32] = ma[5]:ma[4]
568 */
569
570 /* Store local copy */
571 memcpy(cmac->instance->mac_addr, ma, 6);
572
573 lo = ((u32) ma[1] << 8) | (u32) ma[0];
574 mid = ((u32) ma[3] << 8) | (u32) ma[2];
575 hi = ((u32) ma[5] << 8) | (u32) ma[4];
576
577 /* Disable Rx/Tx MAC before configuring it. */
578 if (enabled)
579 pm3393_disable(cmac, MAC_DIRECTION_RX | MAC_DIRECTION_TX);
580
581 /* Set RXXG Station Address */
582 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_SA_15_0, lo);
583 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_SA_31_16, mid);
584 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_SA_47_32, hi);
585
586 /* Set TXXG Station Address */
587 pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_SA_15_0, lo);
588 pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_SA_31_16, mid);
589 pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_SA_47_32, hi);
590
591 /* Setup Exact Match Filter 1 with our MAC address
592 *
593 * Must disable exact match filter before configuring it.
594 */
595 pmread(cmac, SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_0, &val);
596 val &= 0xff0f;
597 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_0, val);
598
599 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_1_LOW, lo);
600 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_1_MID, mid);
601 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_1_HIGH, hi);
602
603 val |= 0x0090;
604 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_0, val);
605
606 if (enabled)
607 pm3393_enable(cmac, enabled);
608 return 0;
609}
610
611static void pm3393_destroy(struct cmac *cmac)
612{
613 kfree(cmac);
614}
615
616static struct cmac_ops pm3393_ops = {
617 .destroy = pm3393_destroy,
618 .reset = pm3393_reset,
619 .interrupt_enable = pm3393_interrupt_enable,
620 .interrupt_disable = pm3393_interrupt_disable,
621 .interrupt_clear = pm3393_interrupt_clear,
622 .interrupt_handler = pm3393_interrupt_handler,
623 .enable = pm3393_enable_port,
624 .disable = pm3393_disable,
625 .loopback_enable = pm3393_loopback_enable,
626 .loopback_disable = pm3393_loopback_disable,
627 .set_mtu = pm3393_set_mtu,
628 .set_rx_mode = pm3393_set_rx_mode,
629 .get_speed_duplex_fc = pm3393_get_speed_duplex_fc,
630 .set_speed_duplex_fc = pm3393_set_speed_duplex_fc,
631 .statistics_update = pm3393_update_statistics,
632 .macaddress_get = pm3393_macaddress_get,
633 .macaddress_set = pm3393_macaddress_set
634};
635
636static struct cmac *pm3393_mac_create(adapter_t *adapter, int index)
637{
638 struct cmac *cmac;
639
Stephen Hemminger12702662006-12-01 16:36:14 -0800640 cmac = kzalloc(sizeof(*cmac) + sizeof(cmac_instance), GFP_KERNEL);
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800641 if (!cmac)
642 return NULL;
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800643
644 cmac->ops = &pm3393_ops;
645 cmac->instance = (cmac_instance *) (cmac + 1);
646 cmac->adapter = adapter;
647 cmac->instance->fc = PAUSE_TX | PAUSE_RX;
648
649 t1_tpi_write(adapter, OFFSET(0x0001), 0x00008000);
650 t1_tpi_write(adapter, OFFSET(0x0001), 0x00000000);
651 t1_tpi_write(adapter, OFFSET(0x2308), 0x00009800);
652 t1_tpi_write(adapter, OFFSET(0x2305), 0x00001001); /* PL4IO Enable */
653 t1_tpi_write(adapter, OFFSET(0x2320), 0x00008800);
654 t1_tpi_write(adapter, OFFSET(0x2321), 0x00008800);
655 t1_tpi_write(adapter, OFFSET(0x2322), 0x00008800);
656 t1_tpi_write(adapter, OFFSET(0x2323), 0x00008800);
657 t1_tpi_write(adapter, OFFSET(0x2324), 0x00008800);
658 t1_tpi_write(adapter, OFFSET(0x2325), 0x00008800);
659 t1_tpi_write(adapter, OFFSET(0x2326), 0x00008800);
660 t1_tpi_write(adapter, OFFSET(0x2327), 0x00008800);
661 t1_tpi_write(adapter, OFFSET(0x2328), 0x00008800);
662 t1_tpi_write(adapter, OFFSET(0x2329), 0x00008800);
663 t1_tpi_write(adapter, OFFSET(0x232a), 0x00008800);
664 t1_tpi_write(adapter, OFFSET(0x232b), 0x00008800);
665 t1_tpi_write(adapter, OFFSET(0x232c), 0x00008800);
666 t1_tpi_write(adapter, OFFSET(0x232d), 0x00008800);
667 t1_tpi_write(adapter, OFFSET(0x232e), 0x00008800);
668 t1_tpi_write(adapter, OFFSET(0x232f), 0x00008800);
669 t1_tpi_write(adapter, OFFSET(0x230d), 0x00009c00);
670 t1_tpi_write(adapter, OFFSET(0x2304), 0x00000202); /* PL4IO Calendar Repetitions */
671
672 t1_tpi_write(adapter, OFFSET(0x3200), 0x00008080); /* EFLX Enable */
673 t1_tpi_write(adapter, OFFSET(0x3210), 0x00000000); /* EFLX Channel Deprovision */
674 t1_tpi_write(adapter, OFFSET(0x3203), 0x00000000); /* EFLX Low Limit */
675 t1_tpi_write(adapter, OFFSET(0x3204), 0x00000040); /* EFLX High Limit */
676 t1_tpi_write(adapter, OFFSET(0x3205), 0x000002cc); /* EFLX Almost Full */
677 t1_tpi_write(adapter, OFFSET(0x3206), 0x00000199); /* EFLX Almost Empty */
678 t1_tpi_write(adapter, OFFSET(0x3207), 0x00000240); /* EFLX Cut Through Threshold */
679 t1_tpi_write(adapter, OFFSET(0x3202), 0x00000000); /* EFLX Indirect Register Update */
680 t1_tpi_write(adapter, OFFSET(0x3210), 0x00000001); /* EFLX Channel Provision */
681 t1_tpi_write(adapter, OFFSET(0x3208), 0x0000ffff); /* EFLX Undocumented */
682 t1_tpi_write(adapter, OFFSET(0x320a), 0x0000ffff); /* EFLX Undocumented */
683 t1_tpi_write(adapter, OFFSET(0x320c), 0x0000ffff); /* EFLX enable overflow interrupt The other bit are undocumented */
684 t1_tpi_write(adapter, OFFSET(0x320e), 0x0000ffff); /* EFLX Undocumented */
685
686 t1_tpi_write(adapter, OFFSET(0x2200), 0x0000c000); /* IFLX Configuration - enable */
687 t1_tpi_write(adapter, OFFSET(0x2201), 0x00000000); /* IFLX Channel Deprovision */
688 t1_tpi_write(adapter, OFFSET(0x220e), 0x00000000); /* IFLX Low Limit */
689 t1_tpi_write(adapter, OFFSET(0x220f), 0x00000100); /* IFLX High Limit */
690 t1_tpi_write(adapter, OFFSET(0x2210), 0x00000c00); /* IFLX Almost Full Limit */
691 t1_tpi_write(adapter, OFFSET(0x2211), 0x00000599); /* IFLX Almost Empty Limit */
692 t1_tpi_write(adapter, OFFSET(0x220d), 0x00000000); /* IFLX Indirect Register Update */
693 t1_tpi_write(adapter, OFFSET(0x2201), 0x00000001); /* IFLX Channel Provision */
694 t1_tpi_write(adapter, OFFSET(0x2203), 0x0000ffff); /* IFLX Undocumented */
695 t1_tpi_write(adapter, OFFSET(0x2205), 0x0000ffff); /* IFLX Undocumented */
696 t1_tpi_write(adapter, OFFSET(0x2209), 0x0000ffff); /* IFLX Enable overflow interrupt. The other bit are undocumented */
697
698 t1_tpi_write(adapter, OFFSET(0x2241), 0xfffffffe); /* PL4MOS Undocumented */
699 t1_tpi_write(adapter, OFFSET(0x2242), 0x0000ffff); /* PL4MOS Undocumented */
700 t1_tpi_write(adapter, OFFSET(0x2243), 0x00000008); /* PL4MOS Starving Burst Size */
701 t1_tpi_write(adapter, OFFSET(0x2244), 0x00000008); /* PL4MOS Hungry Burst Size */
702 t1_tpi_write(adapter, OFFSET(0x2245), 0x00000008); /* PL4MOS Transfer Size */
703 t1_tpi_write(adapter, OFFSET(0x2240), 0x00000005); /* PL4MOS Disable */
704
705 t1_tpi_write(adapter, OFFSET(0x2280), 0x00002103); /* PL4ODP Training Repeat and SOP rule */
706 t1_tpi_write(adapter, OFFSET(0x2284), 0x00000000); /* PL4ODP MAX_T setting */
707
708 t1_tpi_write(adapter, OFFSET(0x3280), 0x00000087); /* PL4IDU Enable data forward, port state machine. Set ALLOW_NON_ZERO_OLB */
709 t1_tpi_write(adapter, OFFSET(0x3282), 0x0000001f); /* PL4IDU Enable Dip4 check error interrupts */
710
711 t1_tpi_write(adapter, OFFSET(0x3040), 0x0c32); /* # TXXG Config */
712 /* For T1 use timer based Mac flow control. */
Scott Bardone559fb512005-06-23 01:40:19 -0400713 t1_tpi_write(adapter, OFFSET(0x304d), 0x8000);
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800714 t1_tpi_write(adapter, OFFSET(0x2040), 0x059c); /* # RXXG Config */
Scott Bardone559fb512005-06-23 01:40:19 -0400715 t1_tpi_write(adapter, OFFSET(0x2049), 0x0001); /* # RXXG Cut Through */
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800716 t1_tpi_write(adapter, OFFSET(0x2070), 0x0000); /* # Disable promiscuous mode */
717
718 /* Setup Exact Match Filter 0 to allow broadcast packets.
719 */
720 t1_tpi_write(adapter, OFFSET(0x206e), 0x0000); /* # Disable Match Enable bit */
721 t1_tpi_write(adapter, OFFSET(0x204a), 0xffff); /* # low addr */
722 t1_tpi_write(adapter, OFFSET(0x204b), 0xffff); /* # mid addr */
723 t1_tpi_write(adapter, OFFSET(0x204c), 0xffff); /* # high addr */
724 t1_tpi_write(adapter, OFFSET(0x206e), 0x0009); /* # Enable Match Enable bit */
725
726 t1_tpi_write(adapter, OFFSET(0x0003), 0x0000); /* # NO SOP/ PAD_EN setup */
727 t1_tpi_write(adapter, OFFSET(0x0100), 0x0ff0); /* # RXEQB disabled */
728 t1_tpi_write(adapter, OFFSET(0x0101), 0x0f0f); /* # No Preemphasis */
729
730 return cmac;
731}
732
733static int pm3393_mac_reset(adapter_t * adapter)
734{
735 u32 val;
736 u32 x;
737 u32 is_pl4_reset_finished;
738 u32 is_pl4_outof_lock;
739 u32 is_xaui_mabc_pll_locked;
740 u32 successful_reset;
741 int i;
742
743 /* The following steps are required to properly reset
744 * the PM3393. This information is provided in the
745 * PM3393 datasheet (Issue 2: November 2002)
746 * section 13.1 -- Device Reset.
747 *
748 * The PM3393 has three types of components that are
749 * individually reset:
750 *
751 * DRESETB - Digital circuitry
752 * PL4_ARESETB - PL4 analog circuitry
753 * XAUI_ARESETB - XAUI bus analog circuitry
754 *
755 * Steps to reset PM3393 using RSTB pin:
756 *
757 * 1. Assert RSTB pin low ( write 0 )
758 * 2. Wait at least 1ms to initiate a complete initialization of device.
759 * 3. Wait until all external clocks and REFSEL are stable.
760 * 4. Wait minimum of 1ms. (after external clocks and REFEL are stable)
761 * 5. De-assert RSTB ( write 1 )
762 * 6. Wait until internal timers to expires after ~14ms.
763 * - Allows analog clock synthesizer(PL4CSU) to stabilize to
764 * selected reference frequency before allowing the digital
765 * portion of the device to operate.
766 * 7. Wait at least 200us for XAUI interface to stabilize.
767 * 8. Verify the PM3393 came out of reset successfully.
768 * Set successful reset flag if everything worked else try again
769 * a few more times.
770 */
771
772 successful_reset = 0;
773 for (i = 0; i < 3 && !successful_reset; i++) {
774 /* 1 */
775 t1_tpi_read(adapter, A_ELMER0_GPO, &val);
776 val &= ~1;
777 t1_tpi_write(adapter, A_ELMER0_GPO, val);
778
779 /* 2 */
780 msleep(1);
781
782 /* 3 */
783 msleep(1);
784
785 /* 4 */
786 msleep(2 /*1 extra ms for safety */ );
787
788 /* 5 */
789 val |= 1;
790 t1_tpi_write(adapter, A_ELMER0_GPO, val);
791
792 /* 6 */
793 msleep(15 /*1 extra ms for safety */ );
794
795 /* 7 */
796 msleep(1);
797
798 /* 8 */
799
800 /* Has PL4 analog block come out of reset correctly? */
801 t1_tpi_read(adapter, OFFSET(SUNI1x10GEXP_REG_DEVICE_STATUS), &val);
802 is_pl4_reset_finished = (val & SUNI1x10GEXP_BITMSK_TOP_EXPIRED);
803
804 /* TBD XXX SUNI1x10GEXP_BITMSK_TOP_PL4_IS_DOOL gets locked later in the init sequence
805 * figure out why? */
806
807 /* Have all PL4 block clocks locked? */
808 x = (SUNI1x10GEXP_BITMSK_TOP_PL4_ID_DOOL
809 /*| SUNI1x10GEXP_BITMSK_TOP_PL4_IS_DOOL */ |
810 SUNI1x10GEXP_BITMSK_TOP_PL4_ID_ROOL |
811 SUNI1x10GEXP_BITMSK_TOP_PL4_IS_ROOL |
812 SUNI1x10GEXP_BITMSK_TOP_PL4_OUT_ROOL);
813 is_pl4_outof_lock = (val & x);
814
815 /* ??? If this fails, might be able to software reset the XAUI part
816 * and try to recover... thus saving us from doing another HW reset */
817 /* Has the XAUI MABC PLL circuitry stablized? */
818 is_xaui_mabc_pll_locked =
819 (val & SUNI1x10GEXP_BITMSK_TOP_SXRA_EXPIRED);
820
821 successful_reset = (is_pl4_reset_finished && !is_pl4_outof_lock
822 && is_xaui_mabc_pll_locked);
Stephen Hemmingerf1d3d382006-12-01 16:36:16 -0800823
824 CH_DBG(adapter, HW,
825 "PM3393 HW reset %d: pl4_reset 0x%x, val 0x%x, "
826 "is_pl4_outof_lock 0x%x, xaui_locked 0x%x\n",
827 i, is_pl4_reset_finished, val, is_pl4_outof_lock,
828 is_xaui_mabc_pll_locked);
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800829 }
830 return successful_reset ? 0 : 1;
831}
832
833struct gmac t1_pm3393_ops = {
834 STATS_TICK_SECS,
835 pm3393_mac_create,
836 pm3393_mac_reset
837};