1
2
3
4
5
6#include "gmac.h"
7#include "elmer0.h"
8#include "vsc7326_reg.h"
9
10
11#define STATS_TICK_SECS 15
12
13#define MAJOR_UPDATE_TICKS (1800 / STATS_TICK_SECS)
14
15
16
17
18
19
20#define WM_DISABLE 0x01a01fff
21#define WM_ENABLE 0x014a03F0
22
23struct init_table {
24 u32 addr;
25 u32 data;
26};
27
28struct _cmac_instance {
29 u32 index;
30 u32 ticks;
31};
32
33#define INITBLOCK_SLEEP 0xffffffff
34
35static void vsc_read(adapter_t *adapter, u32 addr, u32 *val)
36{
37 u32 status, vlo, vhi;
38 int i;
39
40 spin_lock_bh(&adapter->mac_lock);
41 t1_tpi_read(adapter, (addr << 2) + 4, &vlo);
42 i = 0;
43 do {
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;
47 i++;
48 } while (((status & 1) == 0) && (i < 50));
49 if (i == 50)
50 pr_err("Invalid tpi read from MAC, breaking loop.\n");
51
52 t1_tpi_read(adapter, (REG_LOCAL_DATA << 2) + 4, &vlo);
53 t1_tpi_read(adapter, REG_LOCAL_DATA << 2, &vhi);
54
55 *val = (vhi << 16) | vlo;
56
57
58
59
60 spin_unlock_bh(&adapter->mac_lock);
61}
62
63static void vsc_write(adapter_t *adapter, u32 addr, u32 data)
64{
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
69
70
71 spin_unlock_bh(&adapter->mac_lock);
72}
73
74
75static void vsc7326_full_reset(adapter_t* adapter)
76{
77 u32 val;
78 u32 result = 0xffff;
79
80 t1_tpi_read(adapter, A_ELMER0_GPO, &val);
81 val &= ~1;
82 t1_tpi_write(adapter, A_ELMER0_GPO, val);
83 udelay(2);
84 val |= 0x1;
85 val |= 0x800;
86 t1_tpi_write(adapter, A_ELMER0_GPO, val);
87 mdelay(1);
88 vsc_write(adapter, REG_SW_RESET, 0x80000001);
89 do {
90 mdelay(1);
91 vsc_read(adapter, REG_SW_RESET, &result);
92 } while (result != 0x0);
93}
94
95static 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 },
111};
112
113static struct init_table vsc7326_portinit[4][22] = {
114 {
115
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 },
130
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 },
139 },
140 {
141
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 },
156
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 },
165 },
166 {
167
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 },
182
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 },
191 },
192 {
193
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 },
208
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 },
217 },
218};
219
220static void run_table(adapter_t *adapter, struct init_table *ib, int len)
221{
222 int i;
223
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);
228 } else
229 vsc_write( adapter, ib[i].addr, ib[i].data );
230 }
231}
232
233static int bist_rd(adapter_t *adapter, int moduleid, int address)
234{
235 int data = 0;
236 u32 result = 0;
237
238 if ((address != 0x0) &&
239 (address != 0x1) &&
240 (address != 0x2) &&
241 (address != 0xd) &&
242 (address != 0xe))
243 pr_err("No bist address: 0x%x\n", address);
244
245 data = ((0x00 << 24) | ((address & 0xff) << 16) | (0x00 << 8) |
246 ((moduleid & 0xff) << 0));
247 vsc_write(adapter, REG_RAM_BIST_CMD, data);
248
249 udelay(10);
250
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);
256
257 return result & 0xff;
258}
259
260static int bist_wr(adapter_t *adapter, int moduleid, int address, int value)
261{
262 int data = 0;
263 u32 result = 0;
264
265 if ((address != 0x0) &&
266 (address != 0x1) &&
267 (address != 0x2) &&
268 (address != 0xd) &&
269 (address != 0xe))
270 pr_err("No bist address: 0x%x\n", address);
271
272 if (value > 255)
273 pr_err("Suspicious write out of range value: 0x%x\n", value);
274
275 data = ((0x01 << 24) | ((address & 0xff) << 16) | (value << 8) |
276 ((moduleid & 0xff) << 0));
277 vsc_write(adapter, REG_RAM_BIST_CMD, data);
278
279 udelay(5);
280
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);
286
287 return 0;
288}
289
290static int run_bist(adapter_t *adapter, int moduleid)
291{
292
293 (void) bist_wr(adapter,moduleid, 0x00, 0x02);
294 (void) bist_wr(adapter,moduleid, 0x01, 0x01);
295
296 return 0;
297}
298
299static int check_bist(adapter_t *adapter, int moduleid)
300{
301 int result=0;
302 int column=0;
303
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);
310 return 0;
311}
312
313static int enable_mem(adapter_t *adapter, int moduleid)
314{
315
316 (void) bist_wr(adapter,moduleid, 0x00, 0x00);
317 return 0;
318}
319
320static int run_bist_all(adapter_t *adapter)
321{
322 int port = 0;
323 u32 val = 0;
324
325 vsc_write(adapter, REG_MEM_BIST, 0x5);
326 vsc_read(adapter, REG_MEM_BIST, &val);
327
328 for (port = 0; port < 12; port++)
329 vsc_write(adapter, REG_DEV_SETUP(port), 0x0);
330
331 udelay(300);
332 vsc_write(adapter, REG_SPI4_MISC, 0x00040409);
333 udelay(300);
334
335 (void) run_bist(adapter,13);
336 (void) run_bist(adapter,14);
337 (void) run_bist(adapter,20);
338 (void) run_bist(adapter,21);
339 mdelay(200);
340 (void) check_bist(adapter,13);
341 (void) check_bist(adapter,14);
342 (void) check_bist(adapter,20);
343 (void) check_bist(adapter,21);
344 udelay(100);
345 (void) enable_mem(adapter,13);
346 (void) enable_mem(adapter,14);
347 (void) enable_mem(adapter,20);
348 (void) enable_mem(adapter,21);
349 udelay(300);
350 vsc_write(adapter, REG_SPI4_MISC, 0x60040400);
351 udelay(300);
352 for (port = 0; port < 12; port++)
353 vsc_write(adapter, REG_DEV_SETUP(port), 0x1);
354
355 udelay(300);
356 vsc_write(adapter, REG_MEM_BIST, 0x0);
357 mdelay(10);
358 return 0;
359}
360
361static int mac_intr_handler(struct cmac *mac)
362{
363 return 0;
364}
365
366static int mac_intr_enable(struct cmac *mac)
367{
368 return 0;
369}
370
371static int mac_intr_disable(struct cmac *mac)
372{
373 return 0;
374}
375
376static int mac_intr_clear(struct cmac *mac)
377{
378 return 0;
379}
380
381
382static int mac_set_address(struct cmac* mac, u8 addr[6])
383{
384 u32 val;
385 int port = mac->instance->index;
386
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]);
391
392 vsc_read(mac->adapter, REG_ING_FFILT_UM_EN, &val);
393 val &= ~0xf0000000;
394 vsc_write(mac->adapter, REG_ING_FFILT_UM_EN, val | (port << 28));
395
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]);
402 return 0;
403}
404
405static int mac_get_address(struct cmac *mac, u8 addr[6])
406{
407 u32 addr_lo, addr_hi;
408 int port = mac->instance->index;
409
410 vsc_read(mac->adapter, REG_MAC_LOW_ADDR(port), &addr_lo);
411 vsc_read(mac->adapter, REG_MAC_HIGH_ADDR(port), &addr_hi);
412
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;
419 return 0;
420}
421
422
423static int mac_reset(struct cmac *mac)
424{
425 int index = mac->instance->index;
426
427 run_table(mac->adapter, vsc7326_portinit[index],
428 ARRAY_SIZE(vsc7326_portinit[index]));
429
430 return 0;
431}
432
433static int mac_set_rx_mode(struct cmac *mac, struct t1_rx_mode *rm)
434{
435 u32 v;
436 int port = mac->instance->index;
437
438 vsc_read(mac->adapter, REG_ING_FFILT_UM_EN, &v);
439 v |= 1 << 12;
440
441 if (t1_rx_mode_promisc(rm))
442 v &= ~(1 << (port + 16));
443 else
444 v |= 1 << (port + 16);
445
446 vsc_write(mac->adapter, REG_ING_FFILT_UM_EN, v);
447 return 0;
448}
449
450static int mac_set_mtu(struct cmac *mac, int mtu)
451{
452 int port = mac->instance->index;
453
454
455 vsc_write(mac->adapter, REG_MAX_LEN(port), mtu + 14 + 4);
456 return 0;
457}
458
459static int mac_set_speed_duplex_fc(struct cmac *mac, int speed, int duplex,
460 int fc)
461{
462 u32 v;
463 int enable, port = mac->instance->index;
464
465 if (speed >= 0 && speed != SPEED_10 && speed != SPEED_100 &&
466 speed != SPEED_1000)
467 return -1;
468 if (duplex > 0 && duplex != DUPLEX_FULL)
469 return -1;
470
471 if (speed >= 0) {
472 vsc_read(mac->adapter, REG_MODE_CFG(port), &v);
473 enable = v & 3;
474 v &= ~0xf;
475 v |= 4;
476 if (speed == SPEED_1000)
477 v |= 8;
478 enable |= v;
479 vsc_write(mac->adapter, REG_MODE_CFG(port), v);
480
481 if (speed == SPEED_1000)
482 v = 0x82;
483 else if (speed == SPEED_100)
484 v = 0x84;
485 else
486 v = 0x86;
487 vsc_write(mac->adapter, REG_DEV_SETUP(port), v | 1);
488 vsc_write(mac->adapter, REG_DEV_SETUP(port), v);
489 vsc_read(mac->adapter, REG_DBG(port), &v);
490 v &= ~0xff00;
491 if (speed == SPEED_1000)
492 v |= 0x400;
493 else if (speed == SPEED_100)
494 v |= 0x2000;
495 else
496 v |= 0xff00;
497 vsc_write(mac->adapter, REG_DBG(port), v);
498
499 vsc_write(mac->adapter, REG_TX_IFG(port),
500 speed == SPEED_1000 ? 5 : 0x11);
501 if (duplex == DUPLEX_HALF)
502 enable = 0x0;
503 else if (speed == SPEED_1000)
504 enable = 0xc;
505 else
506 enable = 0x4;
507 enable |= 0x9 << 10;
508 enable |= 0x6 << 6;
509 enable |= 0x1 << 4;
510 enable |= 0x3;
511 vsc_write(mac->adapter, REG_MODE_CFG(port), enable);
512
513 }
514
515 vsc_read(mac->adapter, REG_PAUSE_CFG(port), &v);
516 v &= 0xfff0ffff;
517 v |= 0x20000;
518 if (fc & PAUSE_RX)
519 v |= 0x40000;
520 if (fc & PAUSE_TX)
521 v |= 0x80000;
522 if (fc == (PAUSE_RX | PAUSE_TX))
523 v |= 0x10000;
524 vsc_write(mac->adapter, REG_PAUSE_CFG(port), v);
525 return 0;
526}
527
528static int mac_enable(struct cmac *mac, int which)
529{
530 u32 val;
531 int port = mac->instance->index;
532
533
534 vsc_write(mac->adapter, REG_HIGH_LOW_WM(1,port), WM_ENABLE);
535
536 vsc_read(mac->adapter, REG_MODE_CFG(port), &val);
537 if (which & MAC_DIRECTION_RX)
538 val |= 0x2;
539 if (which & MAC_DIRECTION_TX)
540 val |= 1;
541 vsc_write(mac->adapter, REG_MODE_CFG(port), val);
542 return 0;
543}
544
545static int mac_disable(struct cmac *mac, int which)
546{
547 u32 val;
548 int i, port = mac->instance->index;
549
550
551 mac_reset(mac);
552
553 vsc_read(mac->adapter, REG_MODE_CFG(port), &val);
554 if (which & MAC_DIRECTION_RX)
555 val &= ~0x2;
556 if (which & MAC_DIRECTION_TX)
557 val &= ~0x1;
558 vsc_write(mac->adapter, REG_MODE_CFG(port), val);
559 vsc_read(mac->adapter, REG_MODE_CFG(port), &val);
560
561
562 for (i = 0; i <= 0x3a; ++i)
563 vsc_write(mac->adapter, CRA(4, port, i), 0);
564
565
566 memset(&mac->stats, 0, sizeof(struct cmac_statistics));
567
568 return 0;
569}
570
571static void rmon_update(struct cmac *mac, unsigned int addr, u64 *stat)
572{
573 u32 v, lo;
574
575 vsc_read(mac->adapter, addr, &v);
576 lo = *stat;
577 *stat = *stat - lo + v;
578
579 if (v == 0)
580 return;
581
582 if (v < lo)
583 *stat += (1ULL << 32);
584}
585
586static void port_stats_update(struct cmac *mac)
587{
588 struct {
589 unsigned int reg;
590 unsigned int offset;
591 } hw_stats[] = {
592
593#define HW_STAT(reg, stat_name) \
594 { reg, (&((struct cmac_statistics *)NULL)->stat_name) - (u64 *)NULL }
595
596
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),
609
610
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),
617 }, *p = hw_stats;
618 unsigned int port = mac->instance->index;
619 u64 *stats = (u64 *)&mac->stats;
620 unsigned int i;
621
622 for (i = 0; i < ARRAY_SIZE(hw_stats); i++)
623 rmon_update(mac, CRA(0x4, port, p->reg), stats + p->offset);
624
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);
628}
629
630
631
632
633
634
635
636
637
638
639static const struct cmac_statistics *mac_update_statistics(struct cmac *mac,
640 int flag)
641{
642 if (flag == MAC_STATS_UPDATE_FULL ||
643 mac->instance->ticks >= MAJOR_UPDATE_TICKS) {
644 port_stats_update(mac);
645 mac->instance->ticks = 0;
646 } else {
647 int port = mac->instance->index;
648
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++;
656 }
657 return &mac->stats;
658}
659
660static void mac_destroy(struct cmac *mac)
661{
662 kfree(mac);
663}
664
665static const struct cmac_ops vsc7326_ops = {
666 .destroy = mac_destroy,
667 .reset = mac_reset,
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,
680};
681
682static struct cmac *vsc7326_mac_create(adapter_t *adapter, int index)
683{
684 struct cmac *mac;
685 u32 val;
686 int i;
687
688 mac = kzalloc(sizeof(*mac) + sizeof(cmac_instance), GFP_KERNEL);
689 if (!mac)
690 return NULL;
691
692 mac->ops = &vsc7326_ops;
693 mac->instance = (cmac_instance *)(mac + 1);
694 mac->adapter = adapter;
695
696 mac->instance->index = index;
697 mac->instance->ticks = 0;
698
699 i = 0;
700 do {
701 u32 vhi, vlo;
702
703 vhi = vlo = 0;
704 t1_tpi_read(adapter, (REG_LOCAL_STATUS << 2) + 4, &vlo);
705 udelay(1);
706 t1_tpi_read(adapter, REG_LOCAL_STATUS << 2, &vhi);
707 udelay(5);
708 val = (vhi << 16) | vlo;
709 } while ((++i < 10000) && (val == 0xffffffff));
710
711 return mac;
712}
713
714static int vsc7326_mac_reset(adapter_t *adapter)
715{
716 vsc7326_full_reset(adapter);
717 (void) run_bist_all(adapter);
718 run_table(adapter, vsc7326_reset, ARRAY_SIZE(vsc7326_reset));
719 return 0;
720}
721
722const struct gmac t1_vsc7326_ops = {
723 .stats_update_period = STATS_TICK_SECS,
724 .create = vsc7326_mac_create,
725 .reset = vsc7326_mac_reset,
726};
727