License cleanup: add SPDX GPL-2.0 license identifier to files with no license
[linux-block.git] / drivers / net / ethernet / chelsio / cxgb / vsc7326.c
CommitLineData
b2441318 1// SPDX-License-Identifier: GPL-2.0
352c417d
SH
2/* $Date: 2006/04/28 19:20:06 $ $RCSfile: vsc7326.c,v $ $Revision: 1.19 $ */
3
4/* Driver for Vitesse VSC7326 (Schaumburg) MAC */
5
6#include "gmac.h"
7#include "elmer0.h"
8#include "vsc7326_reg.h"
9
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)
14
352c417d
SH
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.
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)
c1f51212 50 pr_err("Invalid tpi read from MAC, breaking loop.\n");
352c417d
SH
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
c1f51212 57 /* pr_err("rd: block: 0x%x sublock: 0x%x reg: 0x%x data: 0x%x\n",
352c417d
SH
58 ((addr&0xe000)>>13), ((addr&0x1e00)>>9),
59 ((addr&0x01fe)>>1), *val); */
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);
c1f51212 68 /* pr_err("wr: block: 0x%x sublock: 0x%x reg: 0x%x data: 0x%x\n",
352c417d
SH
69 ((addr&0xe000)>>13), ((addr&0x1e00)>>9),
70 ((addr&0x01fe)>>1), data); */
71 spin_unlock_bh(&adapter->mac_lock);
72}
73
74/* Hard reset the MAC. This wipes out *all* configuration. */
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; /* Enable mac MAC itself */
85 val |= 0x800; /* Turn off the red LED */
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 { /* Port 0 */
115 /* FIFO setup */
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 /* Port config */
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 { /* Port 1 */
141 /* FIFO setup */
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 /* Port config */
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 { /* Port 2 */
167 /* FIFO setup */
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 /* Port config */
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 { /* Port 3 */
193 /* FIFO setup */
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 /* Port config */
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 );
c1f51212 227 pr_err("sleep %d us\n",ib[i].data);
d7487421 228 } else
352c417d 229 vsc_write( adapter, ib[i].addr, ib[i].data );
352c417d
SH
230 }
231}
232
233static int bist_rd(adapter_t *adapter, int moduleid, int address)
234{
356bd146
FR
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))
c1f51212 243 pr_err("No bist address: 0x%x\n", address);
352c417d
SH
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);
356bd146 252 if ((result & (1 << 9)) != 0x0)
c1f51212 253 pr_err("Still in bist read: 0x%x\n", result);
356bd146 254 else if ((result & (1 << 8)) != 0x0)
c1f51212 255 pr_err("bist read error: 0x%x\n", result);
352c417d 256
807540ba 257 return result & 0xff;
352c417d
SH
258}
259
260static int bist_wr(adapter_t *adapter, int moduleid, int address, int value)
261{
356bd146
FR
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))
c1f51212 270 pr_err("No bist address: 0x%x\n", address);
352c417d 271
356bd146 272 if (value > 255)
c1f51212 273 pr_err("Suspicious write out of range value: 0x%x\n", value);
352c417d
SH
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);
356bd146 282 if ((result & (1 << 27)) != 0x0)
c1f51212 283 pr_err("Still in bist write: 0x%x\n", result);
356bd146 284 else if ((result & (1 << 26)) != 0x0)
c1f51212 285 pr_err("bist write error: 0x%x\n", result);
352c417d 286
b7d58394 287 return 0;
352c417d
SH
288}
289
290static int run_bist(adapter_t *adapter, int moduleid)
291{
292 /*run bist*/
293 (void) bist_wr(adapter,moduleid, 0x00, 0x02);
294 (void) bist_wr(adapter,moduleid, 0x01, 0x01);
295
b7d58394 296 return 0;
352c417d
SH
297}
298
299static int check_bist(adapter_t *adapter, int moduleid)
300{
301 int result=0;
302 int column=0;
303 /*check bist*/
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)
c1f51212 308 pr_err("Result: 0x%x BIST error in ram %d, column: 0x%04x\n",
352c417d 309 result, moduleid, column);
b7d58394 310 return 0;
352c417d
SH
311}
312
313static int enable_mem(adapter_t *adapter, int moduleid)
314{
315 /*enable mem*/
316 (void) bist_wr(adapter,moduleid, 0x00, 0x00);
b7d58394 317 return 0;
352c417d
SH
318}
319
320static int run_bist_all(adapter_t *adapter)
321{
356bd146
FR
322 int port = 0;
323 u32 val = 0;
352c417d
SH
324
325 vsc_write(adapter, REG_MEM_BIST, 0x5);
326 vsc_read(adapter, REG_MEM_BIST, &val);
327
356bd146 328 for (port = 0; port < 12; port++)
352c417d 329 vsc_write(adapter, REG_DEV_SETUP(port), 0x0);
352c417d
SH
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);
356bd146 352 for (port = 0; port < 12; port++)
352c417d 353 vsc_write(adapter, REG_DEV_SETUP(port), 0x1);
356bd146 354
352c417d
SH
355 udelay(300);
356 vsc_write(adapter, REG_MEM_BIST, 0x0);
357 mdelay(10);
b7d58394 358 return 0;
352c417d
SH
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/* Expect MAC address to be in network byte order. */
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/* This is intended to reset a port, not the whole MAC */
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
352c417d
SH
454 /* max_len includes header and FCS */
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; /* save tx/rx enables */
474 v &= ~0xf;
475 v |= 4; /* full duplex */
476 if (speed == SPEED_1000)
477 v |= 8; /* GigE */
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 /* SPEED_10 */
486 v = 0x86;
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);
490 v &= ~0xff00;
491 if (speed == SPEED_1000)
492 v |= 0x400;
493 else if (speed == SPEED_100)
494 v |= 0x2000;
495 else /* SPEED_10 */
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; /* 100 or 10 */
503 else if (speed == SPEED_1000)
504 enable = 0xc;
505 else /* SPEED_100 or 10 */
506 enable = 0x4;
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);
512
513 }
514
515 vsc_read(mac->adapter, REG_PAUSE_CFG(port), &v);
516 v &= 0xfff0ffff;
517 v |= 0x20000; /* xon/xoff */
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 /* Write the correct WM value when the port is enabled. */
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 /* Reset the port, this also writes the correct WM value */
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 /* Clear stats */
562 for (i = 0; i <= 0x3a; ++i)
563 vsc_write(mac->adapter, CRA(4, port, i), 0);
564
25985edc 565 /* Clear software counters */
352c417d
SH
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{
83432468
FR
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 /* Rx stats */
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 /* 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),
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);
352c417d 624
83432468 625 rmon_update(mac, REG_TX_OK_BYTES(port), &mac->stats.TxOctetsOK);
352c417d
SH
626 rmon_update(mac, REG_RX_OK_BYTES(port), &mac->stats.RxOctetsOK);
627 rmon_update(mac, REG_RX_BAD_BYTES(port), &mac->stats.RxOctetsBad);
352c417d
SH
628}
629
630/*
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.
635 *
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.
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
264a4aca 665static const struct cmac_ops vsc7326_ops = {
352c417d
SH
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);
c697f83e
FR
689 if (!mac)
690 return NULL;
352c417d
SH
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
459e536b 722const struct gmac t1_vsc7326_ops = {
352c417d
SH
723 .stats_update_period = STATS_TICK_SECS,
724 .create = vsc7326_mac_create,
725 .reset = vsc7326_mac_reset,
726};