xref: /linux/drivers/net/ethernet/chelsio/cxgb/vsc7326.c (revision e58e871becec2d3b04ed91c0c16fe8deac9c9dfa)
1 /* $Date: 2006/04/28 19:20:06 $ $RCSfile: vsc7326.c,v $ $Revision: 1.19 $ */
2 
3 /* Driver for Vitesse VSC7326 (Schaumburg) MAC */
4 
5 #include "gmac.h"
6 #include "elmer0.h"
7 #include "vsc7326_reg.h"
8 
9 /* Update fast changing statistics every 15 seconds */
10 #define STATS_TICK_SECS 15
11 /* 30 minutes for full statistics update */
12 #define MAJOR_UPDATE_TICKS (1800 / STATS_TICK_SECS)
13 
14 /* The egress WM value 0x01a01fff should be used only when the
15  * interface is down (MAC port disabled). This is a workaround
16  * for disabling the T2/MAC flow-control. When the interface is
17  * enabled, the WM value should be set to 0x014a03F0.
18  */
19 #define WM_DISABLE	0x01a01fff
20 #define WM_ENABLE	0x014a03F0
21 
22 struct init_table {
23 	u32 addr;
24 	u32 data;
25 };
26 
27 struct _cmac_instance {
28 	u32 index;
29 	u32 ticks;
30 };
31 
32 #define INITBLOCK_SLEEP	0xffffffff
33 
34 static void vsc_read(adapter_t *adapter, u32 addr, u32 *val)
35 {
36 	u32 status, vlo, vhi;
37 	int i;
38 
39 	spin_lock_bh(&adapter->mac_lock);
40 	t1_tpi_read(adapter, (addr << 2) + 4, &vlo);
41 	i = 0;
42 	do {
43 		t1_tpi_read(adapter, (REG_LOCAL_STATUS << 2) + 4, &vlo);
44 		t1_tpi_read(adapter, REG_LOCAL_STATUS << 2, &vhi);
45 		status = (vhi << 16) | vlo;
46 		i++;
47 	} while (((status & 1) == 0) && (i < 50));
48 	if (i == 50)
49 		pr_err("Invalid tpi read from MAC, breaking loop.\n");
50 
51 	t1_tpi_read(adapter, (REG_LOCAL_DATA << 2) + 4, &vlo);
52 	t1_tpi_read(adapter, REG_LOCAL_DATA << 2, &vhi);
53 
54 	*val = (vhi << 16) | vlo;
55 
56 	/* pr_err("rd: block: 0x%x  sublock: 0x%x  reg: 0x%x  data: 0x%x\n",
57 		((addr&0xe000)>>13), ((addr&0x1e00)>>9),
58 		((addr&0x01fe)>>1), *val); */
59 	spin_unlock_bh(&adapter->mac_lock);
60 }
61 
62 static void vsc_write(adapter_t *adapter, u32 addr, u32 data)
63 {
64 	spin_lock_bh(&adapter->mac_lock);
65 	t1_tpi_write(adapter, (addr << 2) + 4, data & 0xFFFF);
66 	t1_tpi_write(adapter, addr << 2, (data >> 16) & 0xFFFF);
67 	/* pr_err("wr: block: 0x%x  sublock: 0x%x  reg: 0x%x  data: 0x%x\n",
68 		((addr&0xe000)>>13), ((addr&0x1e00)>>9),
69 		((addr&0x01fe)>>1), data); */
70 	spin_unlock_bh(&adapter->mac_lock);
71 }
72 
73 /* Hard reset the MAC.  This wipes out *all* configuration. */
74 static void vsc7326_full_reset(adapter_t* adapter)
75 {
76 	u32 val;
77 	u32 result = 0xffff;
78 
79 	t1_tpi_read(adapter, A_ELMER0_GPO, &val);
80 	val &= ~1;
81 	t1_tpi_write(adapter, A_ELMER0_GPO, val);
82 	udelay(2);
83 	val |= 0x1;	/* Enable mac MAC itself */
84 	val |= 0x800;	/* Turn off the red LED */
85 	t1_tpi_write(adapter, A_ELMER0_GPO, val);
86 	mdelay(1);
87 	vsc_write(adapter, REG_SW_RESET, 0x80000001);
88 	do {
89 		mdelay(1);
90 		vsc_read(adapter, REG_SW_RESET, &result);
91 	} while (result != 0x0);
92 }
93 
94 static struct init_table vsc7326_reset[] = {
95 	{      REG_IFACE_MODE, 0x00000000 },
96 	{         REG_CRC_CFG, 0x00000020 },
97 	{   REG_PLL_CLK_SPEED, 0x00050c00 },
98 	{   REG_PLL_CLK_SPEED, 0x00050c00 },
99 	{            REG_MSCH, 0x00002f14 },
100 	{       REG_SPI4_MISC, 0x00040409 },
101 	{     REG_SPI4_DESKEW, 0x00080000 },
102 	{ REG_SPI4_ING_SETUP2, 0x08080004 },
103 	{ REG_SPI4_ING_SETUP0, 0x04111004 },
104 	{ REG_SPI4_EGR_SETUP0, 0x80001a04 },
105 	{ REG_SPI4_ING_SETUP1, 0x02010000 },
106 	{      REG_AGE_INC(0), 0x00000000 },
107 	{      REG_AGE_INC(1), 0x00000000 },
108 	{     REG_ING_CONTROL, 0x0a200011 },
109 	{     REG_EGR_CONTROL, 0xa0010091 },
110 };
111 
112 static struct init_table vsc7326_portinit[4][22] = {
113 	{	/* Port 0 */
114 			/* FIFO setup */
115 		{           REG_DBG(0), 0x000004f0 },
116 		{           REG_HDX(0), 0x00073101 },
117 		{        REG_TEST(0,0), 0x00000022 },
118 		{        REG_TEST(1,0), 0x00000022 },
119 		{  REG_TOP_BOTTOM(0,0), 0x003f0000 },
120 		{  REG_TOP_BOTTOM(1,0), 0x00120000 },
121 		{ REG_HIGH_LOW_WM(0,0), 0x07460757 },
122 		{ REG_HIGH_LOW_WM(1,0), WM_DISABLE },
123 		{   REG_CT_THRHLD(0,0), 0x00000000 },
124 		{   REG_CT_THRHLD(1,0), 0x00000000 },
125 		{         REG_BUCKE(0), 0x0002ffff },
126 		{         REG_BUCKI(0), 0x0002ffff },
127 		{        REG_TEST(0,0), 0x00000020 },
128 		{        REG_TEST(1,0), 0x00000020 },
129 			/* Port config */
130 		{       REG_MAX_LEN(0), 0x00002710 },
131 		{     REG_PORT_FAIL(0), 0x00000002 },
132 		{    REG_NORMALIZER(0), 0x00000a64 },
133 		{        REG_DENORM(0), 0x00000010 },
134 		{     REG_STICK_BIT(0), 0x03baa370 },
135 		{     REG_DEV_SETUP(0), 0x00000083 },
136 		{     REG_DEV_SETUP(0), 0x00000082 },
137 		{      REG_MODE_CFG(0), 0x0200259f },
138 	},
139 	{	/* Port 1 */
140 			/* FIFO setup */
141 		{           REG_DBG(1), 0x000004f0 },
142 		{           REG_HDX(1), 0x00073101 },
143 		{        REG_TEST(0,1), 0x00000022 },
144 		{        REG_TEST(1,1), 0x00000022 },
145 		{  REG_TOP_BOTTOM(0,1), 0x007e003f },
146 		{  REG_TOP_BOTTOM(1,1), 0x00240012 },
147 		{ REG_HIGH_LOW_WM(0,1), 0x07460757 },
148 		{ REG_HIGH_LOW_WM(1,1), WM_DISABLE },
149 		{   REG_CT_THRHLD(0,1), 0x00000000 },
150 		{   REG_CT_THRHLD(1,1), 0x00000000 },
151 		{         REG_BUCKE(1), 0x0002ffff },
152 		{         REG_BUCKI(1), 0x0002ffff },
153 		{        REG_TEST(0,1), 0x00000020 },
154 		{        REG_TEST(1,1), 0x00000020 },
155 			/* Port config */
156 		{       REG_MAX_LEN(1), 0x00002710 },
157 		{     REG_PORT_FAIL(1), 0x00000002 },
158 		{    REG_NORMALIZER(1), 0x00000a64 },
159 		{        REG_DENORM(1), 0x00000010 },
160 		{     REG_STICK_BIT(1), 0x03baa370 },
161 		{     REG_DEV_SETUP(1), 0x00000083 },
162 		{     REG_DEV_SETUP(1), 0x00000082 },
163 		{      REG_MODE_CFG(1), 0x0200259f },
164 	},
165 	{	/* Port 2 */
166 			/* FIFO setup */
167 		{           REG_DBG(2), 0x000004f0 },
168 		{           REG_HDX(2), 0x00073101 },
169 		{        REG_TEST(0,2), 0x00000022 },
170 		{        REG_TEST(1,2), 0x00000022 },
171 		{  REG_TOP_BOTTOM(0,2), 0x00bd007e },
172 		{  REG_TOP_BOTTOM(1,2), 0x00360024 },
173 		{ REG_HIGH_LOW_WM(0,2), 0x07460757 },
174 		{ REG_HIGH_LOW_WM(1,2), WM_DISABLE },
175 		{   REG_CT_THRHLD(0,2), 0x00000000 },
176 		{   REG_CT_THRHLD(1,2), 0x00000000 },
177 		{         REG_BUCKE(2), 0x0002ffff },
178 		{         REG_BUCKI(2), 0x0002ffff },
179 		{        REG_TEST(0,2), 0x00000020 },
180 		{        REG_TEST(1,2), 0x00000020 },
181 			/* Port config */
182 		{       REG_MAX_LEN(2), 0x00002710 },
183 		{     REG_PORT_FAIL(2), 0x00000002 },
184 		{    REG_NORMALIZER(2), 0x00000a64 },
185 		{        REG_DENORM(2), 0x00000010 },
186 		{     REG_STICK_BIT(2), 0x03baa370 },
187 		{     REG_DEV_SETUP(2), 0x00000083 },
188 		{     REG_DEV_SETUP(2), 0x00000082 },
189 		{      REG_MODE_CFG(2), 0x0200259f },
190 	},
191 	{	/* Port 3 */
192 			/* FIFO setup */
193 		{           REG_DBG(3), 0x000004f0 },
194 		{           REG_HDX(3), 0x00073101 },
195 		{        REG_TEST(0,3), 0x00000022 },
196 		{        REG_TEST(1,3), 0x00000022 },
197 		{  REG_TOP_BOTTOM(0,3), 0x00fc00bd },
198 		{  REG_TOP_BOTTOM(1,3), 0x00480036 },
199 		{ REG_HIGH_LOW_WM(0,3), 0x07460757 },
200 		{ REG_HIGH_LOW_WM(1,3), WM_DISABLE },
201 		{   REG_CT_THRHLD(0,3), 0x00000000 },
202 		{   REG_CT_THRHLD(1,3), 0x00000000 },
203 		{         REG_BUCKE(3), 0x0002ffff },
204 		{         REG_BUCKI(3), 0x0002ffff },
205 		{        REG_TEST(0,3), 0x00000020 },
206 		{        REG_TEST(1,3), 0x00000020 },
207 			/* Port config */
208 		{       REG_MAX_LEN(3), 0x00002710 },
209 		{     REG_PORT_FAIL(3), 0x00000002 },
210 		{    REG_NORMALIZER(3), 0x00000a64 },
211 		{        REG_DENORM(3), 0x00000010 },
212 		{     REG_STICK_BIT(3), 0x03baa370 },
213 		{     REG_DEV_SETUP(3), 0x00000083 },
214 		{     REG_DEV_SETUP(3), 0x00000082 },
215 		{      REG_MODE_CFG(3), 0x0200259f },
216 	},
217 };
218 
219 static void run_table(adapter_t *adapter, struct init_table *ib, int len)
220 {
221 	int i;
222 
223 	for (i = 0; i < len; i++) {
224 		if (ib[i].addr == INITBLOCK_SLEEP) {
225 			udelay( ib[i].data );
226 			pr_err("sleep %d us\n",ib[i].data);
227 		} else
228 			vsc_write( adapter, ib[i].addr, ib[i].data );
229 	}
230 }
231 
232 static int bist_rd(adapter_t *adapter, int moduleid, int address)
233 {
234 	int data = 0;
235 	u32 result = 0;
236 
237 	if ((address != 0x0) &&
238 	    (address != 0x1) &&
239 	    (address != 0x2) &&
240 	    (address != 0xd) &&
241 	    (address != 0xe))
242 			pr_err("No bist address: 0x%x\n", address);
243 
244 	data = ((0x00 << 24) | ((address & 0xff) << 16) | (0x00 << 8) |
245 		((moduleid & 0xff) << 0));
246 	vsc_write(adapter, REG_RAM_BIST_CMD, data);
247 
248 	udelay(10);
249 
250 	vsc_read(adapter, REG_RAM_BIST_RESULT, &result);
251 	if ((result & (1 << 9)) != 0x0)
252 		pr_err("Still in bist read: 0x%x\n", result);
253 	else if ((result & (1 << 8)) != 0x0)
254 		pr_err("bist read error: 0x%x\n", result);
255 
256 	return result & 0xff;
257 }
258 
259 static int bist_wr(adapter_t *adapter, int moduleid, int address, int value)
260 {
261 	int data = 0;
262 	u32 result = 0;
263 
264 	if ((address != 0x0) &&
265 	    (address != 0x1) &&
266 	    (address != 0x2) &&
267 	    (address != 0xd) &&
268 	    (address != 0xe))
269 			pr_err("No bist address: 0x%x\n", address);
270 
271 	if (value > 255)
272 		pr_err("Suspicious write out of range value: 0x%x\n", value);
273 
274 	data = ((0x01 << 24) | ((address & 0xff) << 16) | (value << 8) |
275 		((moduleid & 0xff) << 0));
276 	vsc_write(adapter, REG_RAM_BIST_CMD, data);
277 
278 	udelay(5);
279 
280 	vsc_read(adapter, REG_RAM_BIST_CMD, &result);
281 	if ((result & (1 << 27)) != 0x0)
282 		pr_err("Still in bist write: 0x%x\n", result);
283 	else if ((result & (1 << 26)) != 0x0)
284 		pr_err("bist write error: 0x%x\n", result);
285 
286 	return 0;
287 }
288 
289 static int run_bist(adapter_t *adapter, int moduleid)
290 {
291 	/*run bist*/
292 	(void) bist_wr(adapter,moduleid, 0x00, 0x02);
293 	(void) bist_wr(adapter,moduleid, 0x01, 0x01);
294 
295 	return 0;
296 }
297 
298 static int check_bist(adapter_t *adapter, int moduleid)
299 {
300 	int result=0;
301 	int column=0;
302 	/*check bist*/
303 	result = bist_rd(adapter,moduleid, 0x02);
304 	column = ((bist_rd(adapter,moduleid, 0x0e)<<8) +
305 			(bist_rd(adapter,moduleid, 0x0d)));
306 	if ((result & 3) != 0x3)
307 		pr_err("Result: 0x%x  BIST error in ram %d, column: 0x%04x\n",
308 			result, moduleid, column);
309 	return 0;
310 }
311 
312 static int enable_mem(adapter_t *adapter, int moduleid)
313 {
314 	/*enable mem*/
315 	(void) bist_wr(adapter,moduleid, 0x00, 0x00);
316 	return 0;
317 }
318 
319 static int run_bist_all(adapter_t *adapter)
320 {
321 	int port = 0;
322 	u32 val = 0;
323 
324 	vsc_write(adapter, REG_MEM_BIST, 0x5);
325 	vsc_read(adapter, REG_MEM_BIST, &val);
326 
327 	for (port = 0; port < 12; port++)
328 		vsc_write(adapter, REG_DEV_SETUP(port), 0x0);
329 
330 	udelay(300);
331 	vsc_write(adapter, REG_SPI4_MISC, 0x00040409);
332 	udelay(300);
333 
334 	(void) run_bist(adapter,13);
335 	(void) run_bist(adapter,14);
336 	(void) run_bist(adapter,20);
337 	(void) run_bist(adapter,21);
338 	mdelay(200);
339 	(void) check_bist(adapter,13);
340 	(void) check_bist(adapter,14);
341 	(void) check_bist(adapter,20);
342 	(void) check_bist(adapter,21);
343 	udelay(100);
344 	(void) enable_mem(adapter,13);
345 	(void) enable_mem(adapter,14);
346 	(void) enable_mem(adapter,20);
347 	(void) enable_mem(adapter,21);
348 	udelay(300);
349 	vsc_write(adapter, REG_SPI4_MISC, 0x60040400);
350 	udelay(300);
351 	for (port = 0; port < 12; port++)
352 		vsc_write(adapter, REG_DEV_SETUP(port), 0x1);
353 
354 	udelay(300);
355 	vsc_write(adapter, REG_MEM_BIST, 0x0);
356 	mdelay(10);
357 	return 0;
358 }
359 
360 static int mac_intr_handler(struct cmac *mac)
361 {
362 	return 0;
363 }
364 
365 static int mac_intr_enable(struct cmac *mac)
366 {
367 	return 0;
368 }
369 
370 static int mac_intr_disable(struct cmac *mac)
371 {
372 	return 0;
373 }
374 
375 static int mac_intr_clear(struct cmac *mac)
376 {
377 	return 0;
378 }
379 
380 /* Expect MAC address to be in network byte order. */
381 static int mac_set_address(struct cmac* mac, u8 addr[6])
382 {
383 	u32 val;
384 	int port = mac->instance->index;
385 
386 	vsc_write(mac->adapter, REG_MAC_LOW_ADDR(port),
387 		  (addr[3] << 16) | (addr[4] << 8) | addr[5]);
388 	vsc_write(mac->adapter, REG_MAC_HIGH_ADDR(port),
389 		  (addr[0] << 16) | (addr[1] << 8) | addr[2]);
390 
391 	vsc_read(mac->adapter, REG_ING_FFILT_UM_EN, &val);
392 	val &= ~0xf0000000;
393 	vsc_write(mac->adapter, REG_ING_FFILT_UM_EN, val | (port << 28));
394 
395 	vsc_write(mac->adapter, REG_ING_FFILT_MASK0,
396 		  0xffff0000 | (addr[4] << 8) | addr[5]);
397 	vsc_write(mac->adapter, REG_ING_FFILT_MASK1,
398 		  0xffff0000 | (addr[2] << 8) | addr[3]);
399 	vsc_write(mac->adapter, REG_ING_FFILT_MASK2,
400 		  0xffff0000 | (addr[0] << 8) | addr[1]);
401 	return 0;
402 }
403 
404 static int mac_get_address(struct cmac *mac, u8 addr[6])
405 {
406 	u32 addr_lo, addr_hi;
407 	int port = mac->instance->index;
408 
409 	vsc_read(mac->adapter, REG_MAC_LOW_ADDR(port), &addr_lo);
410 	vsc_read(mac->adapter, REG_MAC_HIGH_ADDR(port), &addr_hi);
411 
412 	addr[0] = (u8) (addr_hi >> 16);
413 	addr[1] = (u8) (addr_hi >> 8);
414 	addr[2] = (u8) addr_hi;
415 	addr[3] = (u8) (addr_lo >> 16);
416 	addr[4] = (u8) (addr_lo >> 8);
417 	addr[5] = (u8) addr_lo;
418 	return 0;
419 }
420 
421 /* This is intended to reset a port, not the whole MAC */
422 static int mac_reset(struct cmac *mac)
423 {
424 	int index = mac->instance->index;
425 
426 	run_table(mac->adapter, vsc7326_portinit[index],
427 		  ARRAY_SIZE(vsc7326_portinit[index]));
428 
429 	return 0;
430 }
431 
432 static int mac_set_rx_mode(struct cmac *mac, struct t1_rx_mode *rm)
433 {
434 	u32 v;
435 	int port = mac->instance->index;
436 
437 	vsc_read(mac->adapter, REG_ING_FFILT_UM_EN, &v);
438 	v |= 1 << 12;
439 
440 	if (t1_rx_mode_promisc(rm))
441 		v &= ~(1 << (port + 16));
442 	else
443 		v |= 1 << (port + 16);
444 
445 	vsc_write(mac->adapter, REG_ING_FFILT_UM_EN, v);
446 	return 0;
447 }
448 
449 static int mac_set_mtu(struct cmac *mac, int mtu)
450 {
451 	int port = mac->instance->index;
452 
453 	/* max_len includes header and FCS */
454 	vsc_write(mac->adapter, REG_MAX_LEN(port), mtu + 14 + 4);
455 	return 0;
456 }
457 
458 static int mac_set_speed_duplex_fc(struct cmac *mac, int speed, int duplex,
459 				   int fc)
460 {
461 	u32 v;
462 	int enable, port = mac->instance->index;
463 
464 	if (speed >= 0 && speed != SPEED_10 && speed != SPEED_100 &&
465 	    speed != SPEED_1000)
466 		return -1;
467 	if (duplex > 0 && duplex != DUPLEX_FULL)
468 		return -1;
469 
470 	if (speed >= 0) {
471 		vsc_read(mac->adapter, REG_MODE_CFG(port), &v);
472 		enable = v & 3;             /* save tx/rx enables */
473 		v &= ~0xf;
474 		v |= 4;                     /* full duplex */
475 		if (speed == SPEED_1000)
476 			v |= 8;             /* GigE */
477 		enable |= v;
478 		vsc_write(mac->adapter, REG_MODE_CFG(port), v);
479 
480 		if (speed == SPEED_1000)
481 			v = 0x82;
482 		else if (speed == SPEED_100)
483 			v = 0x84;
484 		else	/* SPEED_10 */
485 			v = 0x86;
486 		vsc_write(mac->adapter, REG_DEV_SETUP(port), v | 1); /* reset */
487 		vsc_write(mac->adapter, REG_DEV_SETUP(port), v);
488 		vsc_read(mac->adapter, REG_DBG(port), &v);
489 		v &= ~0xff00;
490 		if (speed == SPEED_1000)
491 			v |= 0x400;
492 		else if (speed == SPEED_100)
493 			v |= 0x2000;
494 		else	/* SPEED_10 */
495 			v |= 0xff00;
496 		vsc_write(mac->adapter, REG_DBG(port), v);
497 
498 		vsc_write(mac->adapter, REG_TX_IFG(port),
499 			  speed == SPEED_1000 ? 5 : 0x11);
500 		if (duplex == DUPLEX_HALF)
501 			enable = 0x0;	/* 100 or 10 */
502 		else if (speed == SPEED_1000)
503 			enable = 0xc;
504 		else	/* SPEED_100 or 10 */
505 			enable = 0x4;
506 		enable |= 0x9 << 10;	/* IFG1 */
507 		enable |= 0x6 << 6;	/* IFG2 */
508 		enable |= 0x1 << 4;	/* VLAN */
509 		enable |= 0x3;		/* RX/TX EN */
510 		vsc_write(mac->adapter, REG_MODE_CFG(port), enable);
511 
512 	}
513 
514 	vsc_read(mac->adapter, REG_PAUSE_CFG(port), &v);
515 	v &= 0xfff0ffff;
516 	v |= 0x20000;      /* xon/xoff */
517 	if (fc & PAUSE_RX)
518 		v |= 0x40000;
519 	if (fc & PAUSE_TX)
520 		v |= 0x80000;
521 	if (fc == (PAUSE_RX | PAUSE_TX))
522 		v |= 0x10000;
523 	vsc_write(mac->adapter, REG_PAUSE_CFG(port), v);
524 	return 0;
525 }
526 
527 static int mac_enable(struct cmac *mac, int which)
528 {
529 	u32 val;
530 	int port = mac->instance->index;
531 
532 	/* Write the correct WM value when the port is enabled. */
533 	vsc_write(mac->adapter, REG_HIGH_LOW_WM(1,port), WM_ENABLE);
534 
535 	vsc_read(mac->adapter, REG_MODE_CFG(port), &val);
536 	if (which & MAC_DIRECTION_RX)
537 		val |= 0x2;
538 	if (which & MAC_DIRECTION_TX)
539 		val |= 1;
540 	vsc_write(mac->adapter, REG_MODE_CFG(port), val);
541 	return 0;
542 }
543 
544 static int mac_disable(struct cmac *mac, int which)
545 {
546 	u32 val;
547 	int i, port = mac->instance->index;
548 
549 	/* Reset the port, this also writes the correct WM value */
550 	mac_reset(mac);
551 
552 	vsc_read(mac->adapter, REG_MODE_CFG(port), &val);
553 	if (which & MAC_DIRECTION_RX)
554 		val &= ~0x2;
555 	if (which & MAC_DIRECTION_TX)
556 		val &= ~0x1;
557 	vsc_write(mac->adapter, REG_MODE_CFG(port), val);
558 	vsc_read(mac->adapter, REG_MODE_CFG(port), &val);
559 
560 	/* Clear stats */
561 	for (i = 0; i <= 0x3a; ++i)
562 		vsc_write(mac->adapter, CRA(4, port, i), 0);
563 
564 	/* Clear software counters */
565 	memset(&mac->stats, 0, sizeof(struct cmac_statistics));
566 
567 	return 0;
568 }
569 
570 static void rmon_update(struct cmac *mac, unsigned int addr, u64 *stat)
571 {
572 	u32 v, lo;
573 
574 	vsc_read(mac->adapter, addr, &v);
575 	lo = *stat;
576 	*stat = *stat - lo + v;
577 
578 	if (v == 0)
579 		return;
580 
581 	if (v < lo)
582 		*stat += (1ULL << 32);
583 }
584 
585 static void port_stats_update(struct cmac *mac)
586 {
587 	struct {
588 		unsigned int reg;
589 		unsigned int offset;
590 	} hw_stats[] = {
591 
592 #define HW_STAT(reg, stat_name) \
593 	{ reg, (&((struct cmac_statistics *)NULL)->stat_name) - (u64 *)NULL }
594 
595 		/* Rx stats */
596 		HW_STAT(RxUnicast, RxUnicastFramesOK),
597 		HW_STAT(RxMulticast, RxMulticastFramesOK),
598 		HW_STAT(RxBroadcast, RxBroadcastFramesOK),
599 		HW_STAT(Crc, RxFCSErrors),
600 		HW_STAT(RxAlignment, RxAlignErrors),
601 		HW_STAT(RxOversize, RxFrameTooLongErrors),
602 		HW_STAT(RxPause, RxPauseFrames),
603 		HW_STAT(RxJabbers, RxJabberErrors),
604 		HW_STAT(RxFragments, RxRuntErrors),
605 		HW_STAT(RxUndersize, RxRuntErrors),
606 		HW_STAT(RxSymbolCarrier, RxSymbolErrors),
607 		HW_STAT(RxSize1519ToMax, RxJumboFramesOK),
608 
609 		/* Tx stats (skip collision stats as we are full-duplex only) */
610 		HW_STAT(TxUnicast, TxUnicastFramesOK),
611 		HW_STAT(TxMulticast, TxMulticastFramesOK),
612 		HW_STAT(TxBroadcast, TxBroadcastFramesOK),
613 		HW_STAT(TxPause, TxPauseFrames),
614 		HW_STAT(TxUnderrun, TxUnderrun),
615 		HW_STAT(TxSize1519ToMax, TxJumboFramesOK),
616 	}, *p = hw_stats;
617 	unsigned int port = mac->instance->index;
618 	u64 *stats = (u64 *)&mac->stats;
619 	unsigned int i;
620 
621 	for (i = 0; i < ARRAY_SIZE(hw_stats); i++)
622 		rmon_update(mac, CRA(0x4, port, p->reg), stats + p->offset);
623 
624 	rmon_update(mac, REG_TX_OK_BYTES(port), &mac->stats.TxOctetsOK);
625 	rmon_update(mac, REG_RX_OK_BYTES(port), &mac->stats.RxOctetsOK);
626 	rmon_update(mac, REG_RX_BAD_BYTES(port), &mac->stats.RxOctetsBad);
627 }
628 
629 /*
630  * This function is called periodically to accumulate the current values of the
631  * RMON counters into the port statistics.  Since the counters are only 32 bits
632  * some of them can overflow in less than a minute at GigE speeds, so this
633  * function should be called every 30 seconds or so.
634  *
635  * To cut down on reading costs we update only the octet counters at each tick
636  * and do a full update at major ticks, which can be every 30 minutes or more.
637  */
638 static const struct cmac_statistics *mac_update_statistics(struct cmac *mac,
639 							   int flag)
640 {
641 	if (flag == MAC_STATS_UPDATE_FULL ||
642 	    mac->instance->ticks >= MAJOR_UPDATE_TICKS) {
643 		port_stats_update(mac);
644 		mac->instance->ticks = 0;
645 	} else {
646 		int port = mac->instance->index;
647 
648 		rmon_update(mac, REG_RX_OK_BYTES(port),
649 			    &mac->stats.RxOctetsOK);
650 		rmon_update(mac, REG_RX_BAD_BYTES(port),
651 			    &mac->stats.RxOctetsBad);
652 		rmon_update(mac, REG_TX_OK_BYTES(port),
653 			    &mac->stats.TxOctetsOK);
654 		mac->instance->ticks++;
655 	}
656 	return &mac->stats;
657 }
658 
659 static void mac_destroy(struct cmac *mac)
660 {
661 	kfree(mac);
662 }
663 
664 static const struct cmac_ops vsc7326_ops = {
665 	.destroy                  = mac_destroy,
666 	.reset                    = mac_reset,
667 	.interrupt_handler        = mac_intr_handler,
668 	.interrupt_enable         = mac_intr_enable,
669 	.interrupt_disable        = mac_intr_disable,
670 	.interrupt_clear          = mac_intr_clear,
671 	.enable                   = mac_enable,
672 	.disable                  = mac_disable,
673 	.set_mtu                  = mac_set_mtu,
674 	.set_rx_mode              = mac_set_rx_mode,
675 	.set_speed_duplex_fc      = mac_set_speed_duplex_fc,
676 	.statistics_update        = mac_update_statistics,
677 	.macaddress_get           = mac_get_address,
678 	.macaddress_set           = mac_set_address,
679 };
680 
681 static struct cmac *vsc7326_mac_create(adapter_t *adapter, int index)
682 {
683 	struct cmac *mac;
684 	u32 val;
685 	int i;
686 
687 	mac = kzalloc(sizeof(*mac) + sizeof(cmac_instance), GFP_KERNEL);
688 	if (!mac)
689 		return NULL;
690 
691 	mac->ops = &vsc7326_ops;
692 	mac->instance = (cmac_instance *)(mac + 1);
693 	mac->adapter  = adapter;
694 
695 	mac->instance->index = index;
696 	mac->instance->ticks = 0;
697 
698 	i = 0;
699 	do {
700 		u32 vhi, vlo;
701 
702 		vhi = vlo = 0;
703 		t1_tpi_read(adapter, (REG_LOCAL_STATUS << 2) + 4, &vlo);
704 		udelay(1);
705 		t1_tpi_read(adapter, REG_LOCAL_STATUS << 2, &vhi);
706 		udelay(5);
707 		val = (vhi << 16) | vlo;
708 	} while ((++i < 10000) && (val == 0xffffffff));
709 
710 	return mac;
711 }
712 
713 static int vsc7326_mac_reset(adapter_t *adapter)
714 {
715 	vsc7326_full_reset(adapter);
716 	(void) run_bist_all(adapter);
717 	run_table(adapter, vsc7326_reset, ARRAY_SIZE(vsc7326_reset));
718 	return 0;
719 }
720 
721 const struct gmac t1_vsc7326_ops = {
722 	.stats_update_period = STATS_TICK_SECS,
723 	.create              = vsc7326_mac_create,
724 	.reset               = vsc7326_mac_reset,
725 };
726