1 // SPDX-License-Identifier: GPL-2.0
2 /* $Date: 2006/04/28 19:20:06 $ $RCSfile: vsc7326.c,v $ $Revision: 1.19 $ */
4 /* Driver for Vitesse VSC7326 (Schaumburg) MAC */
8 #include "vsc7326_reg.h"
10 /* Update fast changing statistics every 15 seconds */
11 #define STATS_TICK_SECS 15
12 /* 30 minutes for full statistics update */
13 #define MAJOR_UPDATE_TICKS (1800 / STATS_TICK_SECS)
15 /* The egress WM value 0x01a01fff should be used only when the
16 * interface is down (MAC port disabled). This is a workaround
17 * for disabling the T2/MAC flow-control. When the interface is
18 * enabled, the WM value should be set to 0x014a03F0.
20 #define WM_DISABLE 0x01a01fff
21 #define WM_ENABLE 0x014a03F0
28 struct _cmac_instance
{
33 #define INITBLOCK_SLEEP 0xffffffff
35 static void vsc_read(adapter_t
*adapter
, u32 addr
, u32
*val
)
40 spin_lock_bh(&adapter
->mac_lock
);
41 t1_tpi_read(adapter
, (addr
<< 2) + 4, &vlo
);
44 t1_tpi_read(adapter
, (REG_LOCAL_STATUS
<< 2) + 4, &vlo
);
45 t1_tpi_read(adapter
, REG_LOCAL_STATUS
<< 2, &vhi
);
46 status
= (vhi
<< 16) | vlo
;
48 } while (((status
& 1) == 0) && (i
< 50));
50 pr_err("Invalid tpi read from MAC, breaking loop.\n");
52 t1_tpi_read(adapter
, (REG_LOCAL_DATA
<< 2) + 4, &vlo
);
53 t1_tpi_read(adapter
, REG_LOCAL_DATA
<< 2, &vhi
);
55 *val
= (vhi
<< 16) | vlo
;
57 /* pr_err("rd: block: 0x%x sublock: 0x%x reg: 0x%x data: 0x%x\n",
58 ((addr&0xe000)>>13), ((addr&0x1e00)>>9),
59 ((addr&0x01fe)>>1), *val); */
60 spin_unlock_bh(&adapter
->mac_lock
);
63 static void vsc_write(adapter_t
*adapter
, u32 addr
, u32 data
)
65 spin_lock_bh(&adapter
->mac_lock
);
66 t1_tpi_write(adapter
, (addr
<< 2) + 4, data
& 0xFFFF);
67 t1_tpi_write(adapter
, addr
<< 2, (data
>> 16) & 0xFFFF);
68 /* pr_err("wr: block: 0x%x sublock: 0x%x reg: 0x%x data: 0x%x\n",
69 ((addr&0xe000)>>13), ((addr&0x1e00)>>9),
70 ((addr&0x01fe)>>1), data); */
71 spin_unlock_bh(&adapter
->mac_lock
);
74 /* Hard reset the MAC. This wipes out *all* configuration. */
75 static void vsc7326_full_reset(adapter_t
* adapter
)
80 t1_tpi_read(adapter
, A_ELMER0_GPO
, &val
);
82 t1_tpi_write(adapter
, A_ELMER0_GPO
, val
);
84 val
|= 0x1; /* Enable mac MAC itself */
85 val
|= 0x800; /* Turn off the red LED */
86 t1_tpi_write(adapter
, A_ELMER0_GPO
, val
);
88 vsc_write(adapter
, REG_SW_RESET
, 0x80000001);
91 vsc_read(adapter
, REG_SW_RESET
, &result
);
92 } while (result
!= 0x0);
95 static struct init_table vsc7326_reset
[] = {
96 { REG_IFACE_MODE
, 0x00000000 },
97 { REG_CRC_CFG
, 0x00000020 },
98 { REG_PLL_CLK_SPEED
, 0x00050c00 },
99 { REG_PLL_CLK_SPEED
, 0x00050c00 },
100 { REG_MSCH
, 0x00002f14 },
101 { REG_SPI4_MISC
, 0x00040409 },
102 { REG_SPI4_DESKEW
, 0x00080000 },
103 { REG_SPI4_ING_SETUP2
, 0x08080004 },
104 { REG_SPI4_ING_SETUP0
, 0x04111004 },
105 { REG_SPI4_EGR_SETUP0
, 0x80001a04 },
106 { REG_SPI4_ING_SETUP1
, 0x02010000 },
107 { REG_AGE_INC(0), 0x00000000 },
108 { REG_AGE_INC(1), 0x00000000 },
109 { REG_ING_CONTROL
, 0x0a200011 },
110 { REG_EGR_CONTROL
, 0xa0010091 },
113 static struct init_table vsc7326_portinit
[4][22] = {
116 { REG_DBG(0), 0x000004f0 },
117 { REG_HDX(0), 0x00073101 },
118 { REG_TEST(0,0), 0x00000022 },
119 { REG_TEST(1,0), 0x00000022 },
120 { REG_TOP_BOTTOM(0,0), 0x003f0000 },
121 { REG_TOP_BOTTOM(1,0), 0x00120000 },
122 { REG_HIGH_LOW_WM(0,0), 0x07460757 },
123 { REG_HIGH_LOW_WM(1,0), WM_DISABLE
},
124 { REG_CT_THRHLD(0,0), 0x00000000 },
125 { REG_CT_THRHLD(1,0), 0x00000000 },
126 { REG_BUCKE(0), 0x0002ffff },
127 { REG_BUCKI(0), 0x0002ffff },
128 { REG_TEST(0,0), 0x00000020 },
129 { REG_TEST(1,0), 0x00000020 },
131 { REG_MAX_LEN(0), 0x00002710 },
132 { REG_PORT_FAIL(0), 0x00000002 },
133 { REG_NORMALIZER(0), 0x00000a64 },
134 { REG_DENORM(0), 0x00000010 },
135 { REG_STICK_BIT(0), 0x03baa370 },
136 { REG_DEV_SETUP(0), 0x00000083 },
137 { REG_DEV_SETUP(0), 0x00000082 },
138 { REG_MODE_CFG(0), 0x0200259f },
142 { REG_DBG(1), 0x000004f0 },
143 { REG_HDX(1), 0x00073101 },
144 { REG_TEST(0,1), 0x00000022 },
145 { REG_TEST(1,1), 0x00000022 },
146 { REG_TOP_BOTTOM(0,1), 0x007e003f },
147 { REG_TOP_BOTTOM(1,1), 0x00240012 },
148 { REG_HIGH_LOW_WM(0,1), 0x07460757 },
149 { REG_HIGH_LOW_WM(1,1), WM_DISABLE
},
150 { REG_CT_THRHLD(0,1), 0x00000000 },
151 { REG_CT_THRHLD(1,1), 0x00000000 },
152 { REG_BUCKE(1), 0x0002ffff },
153 { REG_BUCKI(1), 0x0002ffff },
154 { REG_TEST(0,1), 0x00000020 },
155 { REG_TEST(1,1), 0x00000020 },
157 { REG_MAX_LEN(1), 0x00002710 },
158 { REG_PORT_FAIL(1), 0x00000002 },
159 { REG_NORMALIZER(1), 0x00000a64 },
160 { REG_DENORM(1), 0x00000010 },
161 { REG_STICK_BIT(1), 0x03baa370 },
162 { REG_DEV_SETUP(1), 0x00000083 },
163 { REG_DEV_SETUP(1), 0x00000082 },
164 { REG_MODE_CFG(1), 0x0200259f },
168 { REG_DBG(2), 0x000004f0 },
169 { REG_HDX(2), 0x00073101 },
170 { REG_TEST(0,2), 0x00000022 },
171 { REG_TEST(1,2), 0x00000022 },
172 { REG_TOP_BOTTOM(0,2), 0x00bd007e },
173 { REG_TOP_BOTTOM(1,2), 0x00360024 },
174 { REG_HIGH_LOW_WM(0,2), 0x07460757 },
175 { REG_HIGH_LOW_WM(1,2), WM_DISABLE
},
176 { REG_CT_THRHLD(0,2), 0x00000000 },
177 { REG_CT_THRHLD(1,2), 0x00000000 },
178 { REG_BUCKE(2), 0x0002ffff },
179 { REG_BUCKI(2), 0x0002ffff },
180 { REG_TEST(0,2), 0x00000020 },
181 { REG_TEST(1,2), 0x00000020 },
183 { REG_MAX_LEN(2), 0x00002710 },
184 { REG_PORT_FAIL(2), 0x00000002 },
185 { REG_NORMALIZER(2), 0x00000a64 },
186 { REG_DENORM(2), 0x00000010 },
187 { REG_STICK_BIT(2), 0x03baa370 },
188 { REG_DEV_SETUP(2), 0x00000083 },
189 { REG_DEV_SETUP(2), 0x00000082 },
190 { REG_MODE_CFG(2), 0x0200259f },
194 { REG_DBG(3), 0x000004f0 },
195 { REG_HDX(3), 0x00073101 },
196 { REG_TEST(0,3), 0x00000022 },
197 { REG_TEST(1,3), 0x00000022 },
198 { REG_TOP_BOTTOM(0,3), 0x00fc00bd },
199 { REG_TOP_BOTTOM(1,3), 0x00480036 },
200 { REG_HIGH_LOW_WM(0,3), 0x07460757 },
201 { REG_HIGH_LOW_WM(1,3), WM_DISABLE
},
202 { REG_CT_THRHLD(0,3), 0x00000000 },
203 { REG_CT_THRHLD(1,3), 0x00000000 },
204 { REG_BUCKE(3), 0x0002ffff },
205 { REG_BUCKI(3), 0x0002ffff },
206 { REG_TEST(0,3), 0x00000020 },
207 { REG_TEST(1,3), 0x00000020 },
209 { REG_MAX_LEN(3), 0x00002710 },
210 { REG_PORT_FAIL(3), 0x00000002 },
211 { REG_NORMALIZER(3), 0x00000a64 },
212 { REG_DENORM(3), 0x00000010 },
213 { REG_STICK_BIT(3), 0x03baa370 },
214 { REG_DEV_SETUP(3), 0x00000083 },
215 { REG_DEV_SETUP(3), 0x00000082 },
216 { REG_MODE_CFG(3), 0x0200259f },
220 static void run_table(adapter_t
*adapter
, struct init_table
*ib
, int len
)
224 for (i
= 0; i
< len
; i
++) {
225 if (ib
[i
].addr
== INITBLOCK_SLEEP
) {
226 udelay( ib
[i
].data
);
227 pr_err("sleep %d us\n",ib
[i
].data
);
229 vsc_write( adapter
, ib
[i
].addr
, ib
[i
].data
);
233 static int bist_rd(adapter_t
*adapter
, int moduleid
, int address
)
238 if ((address
!= 0x0) &&
243 pr_err("No bist address: 0x%x\n", address
);
245 data
= ((0x00 << 24) | ((address
& 0xff) << 16) | (0x00 << 8) |
246 ((moduleid
& 0xff) << 0));
247 vsc_write(adapter
, REG_RAM_BIST_CMD
, data
);
251 vsc_read(adapter
, REG_RAM_BIST_RESULT
, &result
);
252 if ((result
& (1 << 9)) != 0x0)
253 pr_err("Still in bist read: 0x%x\n", result
);
254 else if ((result
& (1 << 8)) != 0x0)
255 pr_err("bist read error: 0x%x\n", result
);
257 return result
& 0xff;
260 static int bist_wr(adapter_t
*adapter
, int moduleid
, int address
, int value
)
265 if ((address
!= 0x0) &&
270 pr_err("No bist address: 0x%x\n", address
);
273 pr_err("Suspicious write out of range value: 0x%x\n", value
);
275 data
= ((0x01 << 24) | ((address
& 0xff) << 16) | (value
<< 8) |
276 ((moduleid
& 0xff) << 0));
277 vsc_write(adapter
, REG_RAM_BIST_CMD
, data
);
281 vsc_read(adapter
, REG_RAM_BIST_CMD
, &result
);
282 if ((result
& (1 << 27)) != 0x0)
283 pr_err("Still in bist write: 0x%x\n", result
);
284 else if ((result
& (1 << 26)) != 0x0)
285 pr_err("bist write error: 0x%x\n", result
);
290 static int run_bist(adapter_t
*adapter
, int moduleid
)
293 (void) bist_wr(adapter
,moduleid
, 0x00, 0x02);
294 (void) bist_wr(adapter
,moduleid
, 0x01, 0x01);
299 static int check_bist(adapter_t
*adapter
, int moduleid
)
304 result
= bist_rd(adapter
,moduleid
, 0x02);
305 column
= ((bist_rd(adapter
,moduleid
, 0x0e)<<8) +
306 (bist_rd(adapter
,moduleid
, 0x0d)));
307 if ((result
& 3) != 0x3)
308 pr_err("Result: 0x%x BIST error in ram %d, column: 0x%04x\n",
309 result
, moduleid
, column
);
313 static int enable_mem(adapter_t
*adapter
, int moduleid
)
316 (void) bist_wr(adapter
,moduleid
, 0x00, 0x00);
320 static int run_bist_all(adapter_t
*adapter
)
325 vsc_write(adapter
, REG_MEM_BIST
, 0x5);
326 vsc_read(adapter
, REG_MEM_BIST
, &val
);
328 for (port
= 0; port
< 12; port
++)
329 vsc_write(adapter
, REG_DEV_SETUP(port
), 0x0);
332 vsc_write(adapter
, REG_SPI4_MISC
, 0x00040409);
335 (void) run_bist(adapter
,13);
336 (void) run_bist(adapter
,14);
337 (void) run_bist(adapter
,20);
338 (void) run_bist(adapter
,21);
340 (void) check_bist(adapter
,13);
341 (void) check_bist(adapter
,14);
342 (void) check_bist(adapter
,20);
343 (void) check_bist(adapter
,21);
345 (void) enable_mem(adapter
,13);
346 (void) enable_mem(adapter
,14);
347 (void) enable_mem(adapter
,20);
348 (void) enable_mem(adapter
,21);
350 vsc_write(adapter
, REG_SPI4_MISC
, 0x60040400);
352 for (port
= 0; port
< 12; port
++)
353 vsc_write(adapter
, REG_DEV_SETUP(port
), 0x1);
356 vsc_write(adapter
, REG_MEM_BIST
, 0x0);
361 static int mac_intr_handler(struct cmac
*mac
)
366 static int mac_intr_enable(struct cmac
*mac
)
371 static int mac_intr_disable(struct cmac
*mac
)
376 static int mac_intr_clear(struct cmac
*mac
)
381 /* Expect MAC address to be in network byte order. */
382 static int mac_set_address(struct cmac
* mac
, u8 addr
[6])
385 int port
= mac
->instance
->index
;
387 vsc_write(mac
->adapter
, REG_MAC_LOW_ADDR(port
),
388 (addr
[3] << 16) | (addr
[4] << 8) | addr
[5]);
389 vsc_write(mac
->adapter
, REG_MAC_HIGH_ADDR(port
),
390 (addr
[0] << 16) | (addr
[1] << 8) | addr
[2]);
392 vsc_read(mac
->adapter
, REG_ING_FFILT_UM_EN
, &val
);
394 vsc_write(mac
->adapter
, REG_ING_FFILT_UM_EN
, val
| (port
<< 28));
396 vsc_write(mac
->adapter
, REG_ING_FFILT_MASK0
,
397 0xffff0000 | (addr
[4] << 8) | addr
[5]);
398 vsc_write(mac
->adapter
, REG_ING_FFILT_MASK1
,
399 0xffff0000 | (addr
[2] << 8) | addr
[3]);
400 vsc_write(mac
->adapter
, REG_ING_FFILT_MASK2
,
401 0xffff0000 | (addr
[0] << 8) | addr
[1]);
405 static int mac_get_address(struct cmac
*mac
, u8 addr
[6])
407 u32 addr_lo
, addr_hi
;
408 int port
= mac
->instance
->index
;
410 vsc_read(mac
->adapter
, REG_MAC_LOW_ADDR(port
), &addr_lo
);
411 vsc_read(mac
->adapter
, REG_MAC_HIGH_ADDR(port
), &addr_hi
);
413 addr
[0] = (u8
) (addr_hi
>> 16);
414 addr
[1] = (u8
) (addr_hi
>> 8);
415 addr
[2] = (u8
) addr_hi
;
416 addr
[3] = (u8
) (addr_lo
>> 16);
417 addr
[4] = (u8
) (addr_lo
>> 8);
418 addr
[5] = (u8
) addr_lo
;
422 /* This is intended to reset a port, not the whole MAC */
423 static int mac_reset(struct cmac
*mac
)
425 int index
= mac
->instance
->index
;
427 run_table(mac
->adapter
, vsc7326_portinit
[index
],
428 ARRAY_SIZE(vsc7326_portinit
[index
]));
433 static int mac_set_rx_mode(struct cmac
*mac
, struct t1_rx_mode
*rm
)
436 int port
= mac
->instance
->index
;
438 vsc_read(mac
->adapter
, REG_ING_FFILT_UM_EN
, &v
);
441 if (t1_rx_mode_promisc(rm
))
442 v
&= ~(1 << (port
+ 16));
444 v
|= 1 << (port
+ 16);
446 vsc_write(mac
->adapter
, REG_ING_FFILT_UM_EN
, v
);
450 static int mac_set_mtu(struct cmac
*mac
, int mtu
)
452 int port
= mac
->instance
->index
;
454 /* max_len includes header and FCS */
455 vsc_write(mac
->adapter
, REG_MAX_LEN(port
), mtu
+ 14 + 4);
459 static int mac_set_speed_duplex_fc(struct cmac
*mac
, int speed
, int duplex
,
463 int enable
, port
= mac
->instance
->index
;
465 if (speed
>= 0 && speed
!= SPEED_10
&& speed
!= SPEED_100
&&
468 if (duplex
> 0 && duplex
!= DUPLEX_FULL
)
472 vsc_read(mac
->adapter
, REG_MODE_CFG(port
), &v
);
473 enable
= v
& 3; /* save tx/rx enables */
475 v
|= 4; /* full duplex */
476 if (speed
== SPEED_1000
)
479 vsc_write(mac
->adapter
, REG_MODE_CFG(port
), v
);
481 if (speed
== SPEED_1000
)
483 else if (speed
== SPEED_100
)
487 vsc_write(mac
->adapter
, REG_DEV_SETUP(port
), v
| 1); /* reset */
488 vsc_write(mac
->adapter
, REG_DEV_SETUP(port
), v
);
489 vsc_read(mac
->adapter
, REG_DBG(port
), &v
);
491 if (speed
== SPEED_1000
)
493 else if (speed
== SPEED_100
)
497 vsc_write(mac
->adapter
, REG_DBG(port
), v
);
499 vsc_write(mac
->adapter
, REG_TX_IFG(port
),
500 speed
== SPEED_1000
? 5 : 0x11);
501 if (duplex
== DUPLEX_HALF
)
502 enable
= 0x0; /* 100 or 10 */
503 else if (speed
== SPEED_1000
)
505 else /* SPEED_100 or 10 */
507 enable
|= 0x9 << 10; /* IFG1 */
508 enable
|= 0x6 << 6; /* IFG2 */
509 enable
|= 0x1 << 4; /* VLAN */
510 enable
|= 0x3; /* RX/TX EN */
511 vsc_write(mac
->adapter
, REG_MODE_CFG(port
), enable
);
515 vsc_read(mac
->adapter
, REG_PAUSE_CFG(port
), &v
);
517 v
|= 0x20000; /* xon/xoff */
522 if (fc
== (PAUSE_RX
| PAUSE_TX
))
524 vsc_write(mac
->adapter
, REG_PAUSE_CFG(port
), v
);
528 static int mac_enable(struct cmac
*mac
, int which
)
531 int port
= mac
->instance
->index
;
533 /* Write the correct WM value when the port is enabled. */
534 vsc_write(mac
->adapter
, REG_HIGH_LOW_WM(1,port
), WM_ENABLE
);
536 vsc_read(mac
->adapter
, REG_MODE_CFG(port
), &val
);
537 if (which
& MAC_DIRECTION_RX
)
539 if (which
& MAC_DIRECTION_TX
)
541 vsc_write(mac
->adapter
, REG_MODE_CFG(port
), val
);
545 static int mac_disable(struct cmac
*mac
, int which
)
548 int i
, port
= mac
->instance
->index
;
550 /* Reset the port, this also writes the correct WM value */
553 vsc_read(mac
->adapter
, REG_MODE_CFG(port
), &val
);
554 if (which
& MAC_DIRECTION_RX
)
556 if (which
& MAC_DIRECTION_TX
)
558 vsc_write(mac
->adapter
, REG_MODE_CFG(port
), val
);
559 vsc_read(mac
->adapter
, REG_MODE_CFG(port
), &val
);
562 for (i
= 0; i
<= 0x3a; ++i
)
563 vsc_write(mac
->adapter
, CRA(4, port
, i
), 0);
565 /* Clear software counters */
566 memset(&mac
->stats
, 0, sizeof(struct cmac_statistics
));
571 static void rmon_update(struct cmac
*mac
, unsigned int addr
, u64
*stat
)
575 vsc_read(mac
->adapter
, addr
, &v
);
577 *stat
= *stat
- lo
+ v
;
583 *stat
+= (1ULL << 32);
586 static void port_stats_update(struct cmac
*mac
)
593 #define HW_STAT(reg, stat_name) \
594 { reg, (&((struct cmac_statistics *)NULL)->stat_name) - (u64 *)NULL }
597 HW_STAT(RxUnicast
, RxUnicastFramesOK
),
598 HW_STAT(RxMulticast
, RxMulticastFramesOK
),
599 HW_STAT(RxBroadcast
, RxBroadcastFramesOK
),
600 HW_STAT(Crc
, RxFCSErrors
),
601 HW_STAT(RxAlignment
, RxAlignErrors
),
602 HW_STAT(RxOversize
, RxFrameTooLongErrors
),
603 HW_STAT(RxPause
, RxPauseFrames
),
604 HW_STAT(RxJabbers
, RxJabberErrors
),
605 HW_STAT(RxFragments
, RxRuntErrors
),
606 HW_STAT(RxUndersize
, RxRuntErrors
),
607 HW_STAT(RxSymbolCarrier
, RxSymbolErrors
),
608 HW_STAT(RxSize1519ToMax
, RxJumboFramesOK
),
610 /* Tx stats (skip collision stats as we are full-duplex only) */
611 HW_STAT(TxUnicast
, TxUnicastFramesOK
),
612 HW_STAT(TxMulticast
, TxMulticastFramesOK
),
613 HW_STAT(TxBroadcast
, TxBroadcastFramesOK
),
614 HW_STAT(TxPause
, TxPauseFrames
),
615 HW_STAT(TxUnderrun
, TxUnderrun
),
616 HW_STAT(TxSize1519ToMax
, TxJumboFramesOK
),
618 unsigned int port
= mac
->instance
->index
;
619 u64
*stats
= (u64
*)&mac
->stats
;
622 for (i
= 0; i
< ARRAY_SIZE(hw_stats
); i
++)
623 rmon_update(mac
, CRA(0x4, port
, p
->reg
), stats
+ p
->offset
);
625 rmon_update(mac
, REG_TX_OK_BYTES(port
), &mac
->stats
.TxOctetsOK
);
626 rmon_update(mac
, REG_RX_OK_BYTES(port
), &mac
->stats
.RxOctetsOK
);
627 rmon_update(mac
, REG_RX_BAD_BYTES(port
), &mac
->stats
.RxOctetsBad
);
631 * This function is called periodically to accumulate the current values of the
632 * RMON counters into the port statistics. Since the counters are only 32 bits
633 * some of them can overflow in less than a minute at GigE speeds, so this
634 * function should be called every 30 seconds or so.
636 * To cut down on reading costs we update only the octet counters at each tick
637 * and do a full update at major ticks, which can be every 30 minutes or more.
639 static const struct cmac_statistics
*mac_update_statistics(struct cmac
*mac
,
642 if (flag
== MAC_STATS_UPDATE_FULL
||
643 mac
->instance
->ticks
>= MAJOR_UPDATE_TICKS
) {
644 port_stats_update(mac
);
645 mac
->instance
->ticks
= 0;
647 int port
= mac
->instance
->index
;
649 rmon_update(mac
, REG_RX_OK_BYTES(port
),
650 &mac
->stats
.RxOctetsOK
);
651 rmon_update(mac
, REG_RX_BAD_BYTES(port
),
652 &mac
->stats
.RxOctetsBad
);
653 rmon_update(mac
, REG_TX_OK_BYTES(port
),
654 &mac
->stats
.TxOctetsOK
);
655 mac
->instance
->ticks
++;
660 static void mac_destroy(struct cmac
*mac
)
665 static const struct cmac_ops vsc7326_ops
= {
666 .destroy
= mac_destroy
,
668 .interrupt_handler
= mac_intr_handler
,
669 .interrupt_enable
= mac_intr_enable
,
670 .interrupt_disable
= mac_intr_disable
,
671 .interrupt_clear
= mac_intr_clear
,
672 .enable
= mac_enable
,
673 .disable
= mac_disable
,
674 .set_mtu
= mac_set_mtu
,
675 .set_rx_mode
= mac_set_rx_mode
,
676 .set_speed_duplex_fc
= mac_set_speed_duplex_fc
,
677 .statistics_update
= mac_update_statistics
,
678 .macaddress_get
= mac_get_address
,
679 .macaddress_set
= mac_set_address
,
682 static struct cmac
*vsc7326_mac_create(adapter_t
*adapter
, int index
)
688 mac
= kzalloc(sizeof(*mac
) + sizeof(cmac_instance
), GFP_KERNEL
);
692 mac
->ops
= &vsc7326_ops
;
693 mac
->instance
= (cmac_instance
*)(mac
+ 1);
694 mac
->adapter
= adapter
;
696 mac
->instance
->index
= index
;
697 mac
->instance
->ticks
= 0;
704 t1_tpi_read(adapter
, (REG_LOCAL_STATUS
<< 2) + 4, &vlo
);
706 t1_tpi_read(adapter
, REG_LOCAL_STATUS
<< 2, &vhi
);
708 val
= (vhi
<< 16) | vlo
;
709 } while ((++i
< 10000) && (val
== 0xffffffff));
714 static int vsc7326_mac_reset(adapter_t
*adapter
)
716 vsc7326_full_reset(adapter
);
717 (void) run_bist_all(adapter
);
718 run_table(adapter
, vsc7326_reset
, ARRAY_SIZE(vsc7326_reset
));
722 const struct gmac t1_vsc7326_ops
= {
723 .stats_update_period
= STATS_TICK_SECS
,
724 .create
= vsc7326_mac_create
,
725 .reset
= vsc7326_mac_reset
,