1/* $Date: 2007/08/03 18:52:46 $ $RCSfile: vsc7326.c,v $ $Revision: 1.1.1.1 $ */
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#define MAX_MTU 9600
15
16#define WM_DISABLE	0x01a01fff
17#define WM_ENABLE	0x014a03F0
18
19struct init_table {
20	u32 addr;
21	u32 data;
22};
23
24struct _cmac_instance {
25	u32 index;
26	u32 ticks;
27};
28
29#define INITBLOCK_SLEEP	0xffffffff
30
31static void vsc_read(adapter_t *adapter, u32 addr, u32 *val)
32{
33	u32 status, vlo, vhi;
34	int i;
35
36	spin_lock_bh(&adapter->mac_lock);
37	t1_tpi_read(adapter, (addr << 2) + 4, &vlo);
38	i = 0;
39	do {
40		t1_tpi_read(adapter, (REG_LOCAL_STATUS << 2) + 4, &vlo);
41		t1_tpi_read(adapter, REG_LOCAL_STATUS << 2, &vhi);
42		status = (vhi << 16) | vlo;
43		i++;
44	} while (((status & 1) == 0) && (i < 50));
45	if (i == 50)
46		CH_ERR("Invalid tpi read from MAC, breaking loop.\n");
47
48	t1_tpi_read(adapter, (REG_LOCAL_DATA << 2) + 4, &vlo);
49	t1_tpi_read(adapter, REG_LOCAL_DATA << 2, &vhi);
50
51	*val = (vhi << 16) | vlo;
52
53	/* CH_ERR("rd: block: 0x%x  sublock: 0x%x  reg: 0x%x  data: 0x%x\n",
54		((addr&0xe000)>>13), ((addr&0x1e00)>>9),
55		((addr&0x01fe)>>1), *val); */
56	spin_unlock_bh(&adapter->mac_lock);
57}
58
59static void vsc_write(adapter_t *adapter, u32 addr, u32 data)
60{
61	spin_lock_bh(&adapter->mac_lock);
62	t1_tpi_write(adapter, (addr << 2) + 4, data & 0xFFFF);
63	t1_tpi_write(adapter, addr << 2, (data >> 16) & 0xFFFF);
64	/* CH_ERR("wr: block: 0x%x  sublock: 0x%x  reg: 0x%x  data: 0x%x\n",
65		((addr&0xe000)>>13), ((addr&0x1e00)>>9),
66		((addr&0x01fe)>>1), data); */
67	spin_unlock_bh(&adapter->mac_lock);
68}
69
70/* Hard reset the MAC.  This wipes out *all* configuration. */
71static void vsc7326_full_reset(adapter_t* adapter)
72{
73	u32 val;
74	u32 result = 0xffff;
75
76	t1_tpi_read(adapter, A_ELMER0_GPO, &val);
77	val &= ~1;
78	t1_tpi_write(adapter, A_ELMER0_GPO, val);
79	udelay(2);
80	val |= 0x1;	/* Enable mac MAC itself */
81	val |= 0x800;	/* Turn off the red LED */
82	t1_tpi_write(adapter, A_ELMER0_GPO, val);
83	mdelay(1);
84	vsc_write(adapter, REG_SW_RESET, 0x80000001);
85	do {
86		mdelay(1);
87		vsc_read(adapter, REG_SW_RESET, &result);
88	} while (result != 0x0);
89}
90
91static struct init_table vsc7326_reset[] = {
92	{      REG_IFACE_MODE, 0x00000000 },
93	{         REG_CRC_CFG, 0x00000020 },
94	{   REG_PLL_CLK_SPEED, 0x00050c00 },
95	{   REG_PLL_CLK_SPEED, 0x00050c00 },
96	{            REG_MSCH, 0x00002f14 },
97	{       REG_SPI4_MISC, 0x00040409 },
98	{     REG_SPI4_DESKEW, 0x00080000 },
99	{ REG_SPI4_ING_SETUP2, 0x08080004 },
100	{ REG_SPI4_ING_SETUP0, 0x04111004 },
101	{ REG_SPI4_EGR_SETUP0, 0x80001a04 },
102	{ REG_SPI4_ING_SETUP1, 0x02010000 },
103	{      REG_AGE_INC(0), 0x00000000 },
104	{      REG_AGE_INC(1), 0x00000000 },
105	{     REG_ING_CONTROL, 0x0a200011 },
106	{     REG_EGR_CONTROL, 0xa0010091 },
107};
108
109static struct init_table vsc7326_portinit[4][22] = {
110	{	/* Port 0 */
111			/* FIFO setup */
112		{           REG_DBG(0), 0x000004f0 },
113		{           REG_HDX(0), 0x00073101 },
114		{        REG_TEST(0,0), 0x00000022 },
115		{        REG_TEST(1,0), 0x00000022 },
116		{  REG_TOP_BOTTOM(0,0), 0x003f0000 },
117		{  REG_TOP_BOTTOM(1,0), 0x00120000 },
118		{ REG_HIGH_LOW_WM(0,0), 0x07460757 },
119		{ REG_HIGH_LOW_WM(1,0), WM_DISABLE },
120		{   REG_CT_THRHLD(0,0), 0x00000000 },
121		{   REG_CT_THRHLD(1,0), 0x00000000 },
122		{         REG_BUCKE(0), 0x0002ffff },
123		{         REG_BUCKI(0), 0x0002ffff },
124		{        REG_TEST(0,0), 0x00000020 },
125		{        REG_TEST(1,0), 0x00000020 },
126			/* Port config */
127		{       REG_MAX_LEN(0), 0x00002710 },
128		{     REG_PORT_FAIL(0), 0x00000002 },
129		{    REG_NORMALIZER(0), 0x00000a64 },
130		{        REG_DENORM(0), 0x00000010 },
131		{     REG_STICK_BIT(0), 0x03baa370 },
132		{     REG_DEV_SETUP(0), 0x00000083 },
133		{     REG_DEV_SETUP(0), 0x00000082 },
134		{      REG_MODE_CFG(0), 0x0200259f },
135	},
136	{	/* Port 1 */
137			/* FIFO setup */
138		{           REG_DBG(1), 0x000004f0 },
139		{           REG_HDX(1), 0x00073101 },
140		{        REG_TEST(0,1), 0x00000022 },
141		{        REG_TEST(1,1), 0x00000022 },
142		{  REG_TOP_BOTTOM(0,1), 0x007e003f },
143		{  REG_TOP_BOTTOM(1,1), 0x00240012 },
144		{ REG_HIGH_LOW_WM(0,1), 0x07460757 },
145		{ REG_HIGH_LOW_WM(1,1), WM_DISABLE },
146		{   REG_CT_THRHLD(0,1), 0x00000000 },
147		{   REG_CT_THRHLD(1,1), 0x00000000 },
148		{         REG_BUCKE(1), 0x0002ffff },
149		{         REG_BUCKI(1), 0x0002ffff },
150		{        REG_TEST(0,1), 0x00000020 },
151		{        REG_TEST(1,1), 0x00000020 },
152			/* Port config */
153		{       REG_MAX_LEN(1), 0x00002710 },
154		{     REG_PORT_FAIL(1), 0x00000002 },
155		{    REG_NORMALIZER(1), 0x00000a64 },
156		{        REG_DENORM(1), 0x00000010 },
157		{     REG_STICK_BIT(1), 0x03baa370 },
158		{     REG_DEV_SETUP(1), 0x00000083 },
159		{     REG_DEV_SETUP(1), 0x00000082 },
160		{      REG_MODE_CFG(1), 0x0200259f },
161	},
162	{	/* Port 2 */
163			/* FIFO setup */
164		{           REG_DBG(2), 0x000004f0 },
165		{           REG_HDX(2), 0x00073101 },
166		{        REG_TEST(0,2), 0x00000022 },
167		{        REG_TEST(1,2), 0x00000022 },
168		{  REG_TOP_BOTTOM(0,2), 0x00bd007e },
169		{  REG_TOP_BOTTOM(1,2), 0x00360024 },
170		{ REG_HIGH_LOW_WM(0,2), 0x07460757 },
171		{ REG_HIGH_LOW_WM(1,2), WM_DISABLE },
172		{   REG_CT_THRHLD(0,2), 0x00000000 },
173		{   REG_CT_THRHLD(1,2), 0x00000000 },
174		{         REG_BUCKE(2), 0x0002ffff },
175		{         REG_BUCKI(2), 0x0002ffff },
176		{        REG_TEST(0,2), 0x00000020 },
177		{        REG_TEST(1,2), 0x00000020 },
178			/* Port config */
179		{       REG_MAX_LEN(2), 0x00002710 },
180		{     REG_PORT_FAIL(2), 0x00000002 },
181		{    REG_NORMALIZER(2), 0x00000a64 },
182		{        REG_DENORM(2), 0x00000010 },
183		{     REG_STICK_BIT(2), 0x03baa370 },
184		{     REG_DEV_SETUP(2), 0x00000083 },
185		{     REG_DEV_SETUP(2), 0x00000082 },
186		{      REG_MODE_CFG(2), 0x0200259f },
187	},
188	{	/* Port 3 */
189			/* FIFO setup */
190		{           REG_DBG(3), 0x000004f0 },
191		{           REG_HDX(3), 0x00073101 },
192		{        REG_TEST(0,3), 0x00000022 },
193		{        REG_TEST(1,3), 0x00000022 },
194		{  REG_TOP_BOTTOM(0,3), 0x00fc00bd },
195		{  REG_TOP_BOTTOM(1,3), 0x00480036 },
196		{ REG_HIGH_LOW_WM(0,3), 0x07460757 },
197		{ REG_HIGH_LOW_WM(1,3), WM_DISABLE },
198		{   REG_CT_THRHLD(0,3), 0x00000000 },
199		{   REG_CT_THRHLD(1,3), 0x00000000 },
200		{         REG_BUCKE(3), 0x0002ffff },
201		{         REG_BUCKI(3), 0x0002ffff },
202		{        REG_TEST(0,3), 0x00000020 },
203		{        REG_TEST(1,3), 0x00000020 },
204			/* Port config */
205		{       REG_MAX_LEN(3), 0x00002710 },
206		{     REG_PORT_FAIL(3), 0x00000002 },
207		{    REG_NORMALIZER(3), 0x00000a64 },
208		{        REG_DENORM(3), 0x00000010 },
209		{     REG_STICK_BIT(3), 0x03baa370 },
210		{     REG_DEV_SETUP(3), 0x00000083 },
211		{     REG_DEV_SETUP(3), 0x00000082 },
212		{      REG_MODE_CFG(3), 0x0200259f },
213	},
214};
215
216static void run_table(adapter_t *adapter, struct init_table *ib, int len)
217{
218	int i;
219
220	for (i = 0; i < len; i++) {
221		if (ib[i].addr == INITBLOCK_SLEEP) {
222			udelay( ib[i].data );
223			CH_ERR("sleep %d us\n",ib[i].data);
224		} else
225			vsc_write( adapter, ib[i].addr, ib[i].data );
226	}
227}
228
229static int bist_rd(adapter_t *adapter, int moduleid, int address)
230{
231	int data = 0;
232	u32 result = 0;
233
234	if ((address != 0x0) &&
235	    (address != 0x1) &&
236	    (address != 0x2) &&
237	    (address != 0xd) &&
238	    (address != 0xe))
239			CH_ERR("No bist address: 0x%x\n", address);
240
241	data = ((0x00 << 24) | ((address & 0xff) << 16) | (0x00 << 8) |
242		((moduleid & 0xff) << 0));
243	vsc_write(adapter, REG_RAM_BIST_CMD, data);
244
245	udelay(10);
246
247	vsc_read(adapter, REG_RAM_BIST_RESULT, &result);
248	if ((result & (1 << 9)) != 0x0)
249		CH_ERR("Still in bist read: 0x%x\n", result);
250	else if ((result & (1 << 8)) != 0x0)
251		CH_ERR("bist read error: 0x%x\n", result);
252
253	return (result & 0xff);
254}
255
256static int bist_wr(adapter_t *adapter, int moduleid, int address, int value)
257{
258	int data = 0;
259	u32 result = 0;
260
261	if ((address != 0x0) &&
262	    (address != 0x1) &&
263	    (address != 0x2) &&
264	    (address != 0xd) &&
265	    (address != 0xe))
266			CH_ERR("No bist address: 0x%x\n", address);
267
268	if (value > 255)
269		CH_ERR("Suspicious write out of range value: 0x%x\n", value);
270
271	data = ((0x01 << 24) | ((address & 0xff) << 16) | (value << 8) |
272		((moduleid & 0xff) << 0));
273	vsc_write(adapter, REG_RAM_BIST_CMD, data);
274
275	udelay(5);
276
277	vsc_read(adapter, REG_RAM_BIST_CMD, &result);
278	if ((result & (1 << 27)) != 0x0)
279		CH_ERR("Still in bist write: 0x%x\n", result);
280	else if ((result & (1 << 26)) != 0x0)
281		CH_ERR("bist write error: 0x%x\n", result);
282
283	return 0;
284}
285
286static int run_bist(adapter_t *adapter, int moduleid)
287{
288	/*run bist*/
289	(void) bist_wr(adapter,moduleid, 0x00, 0x02);
290	(void) bist_wr(adapter,moduleid, 0x01, 0x01);
291
292	return 0;
293}
294
295static int check_bist(adapter_t *adapter, int moduleid)
296{
297	int result=0;
298	int column=0;
299	/*check bist*/
300	result = bist_rd(adapter,moduleid, 0x02);
301	column = ((bist_rd(adapter,moduleid, 0x0e)<<8) +
302			(bist_rd(adapter,moduleid, 0x0d)));
303	if ((result & 3) != 0x3)
304		CH_ERR("Result: 0x%x  BIST error in ram %d, column: 0x%04x\n",
305			result, moduleid, column);
306	return 0;
307}
308
309static int enable_mem(adapter_t *adapter, int moduleid)
310{
311	/*enable mem*/
312	(void) bist_wr(adapter,moduleid, 0x00, 0x00);
313	return 0;
314}
315
316static int run_bist_all(adapter_t *adapter)
317{
318	int port = 0;
319	u32 val = 0;
320
321	vsc_write(adapter, REG_MEM_BIST, 0x5);
322	vsc_read(adapter, REG_MEM_BIST, &val);
323
324	for (port = 0; port < 12; port++)
325		vsc_write(adapter, REG_DEV_SETUP(port), 0x0);
326
327	udelay(300);
328	vsc_write(adapter, REG_SPI4_MISC, 0x00040409);
329	udelay(300);
330
331	(void) run_bist(adapter,13);
332	(void) run_bist(adapter,14);
333	(void) run_bist(adapter,20);
334	(void) run_bist(adapter,21);
335	mdelay(200);
336	(void) check_bist(adapter,13);
337	(void) check_bist(adapter,14);
338	(void) check_bist(adapter,20);
339	(void) check_bist(adapter,21);
340	udelay(100);
341	(void) enable_mem(adapter,13);
342	(void) enable_mem(adapter,14);
343	(void) enable_mem(adapter,20);
344	(void) enable_mem(adapter,21);
345	udelay(300);
346	vsc_write(adapter, REG_SPI4_MISC, 0x60040400);
347	udelay(300);
348	for (port = 0; port < 12; port++)
349		vsc_write(adapter, REG_DEV_SETUP(port), 0x1);
350
351	udelay(300);
352	vsc_write(adapter, REG_MEM_BIST, 0x0);
353	mdelay(10);
354	return 0;
355}
356
357static int mac_intr_handler(struct cmac *mac)
358{
359	return 0;
360}
361
362static int mac_intr_enable(struct cmac *mac)
363{
364	return 0;
365}
366
367static int mac_intr_disable(struct cmac *mac)
368{
369	return 0;
370}
371
372static int mac_intr_clear(struct cmac *mac)
373{
374	return 0;
375}
376
377/* Expect MAC address to be in network byte order. */
378static int mac_set_address(struct cmac* mac, u8 addr[6])
379{
380	u32 val;
381	int port = mac->instance->index;
382
383	vsc_write(mac->adapter, REG_MAC_LOW_ADDR(port),
384		  (addr[3] << 16) | (addr[4] << 8) | addr[5]);
385	vsc_write(mac->adapter, REG_MAC_HIGH_ADDR(port),
386		  (addr[0] << 16) | (addr[1] << 8) | addr[2]);
387
388	vsc_read(mac->adapter, REG_ING_FFILT_UM_EN, &val);
389	val &= ~0xf0000000;
390	vsc_write(mac->adapter, REG_ING_FFILT_UM_EN, val | (port << 28));
391
392	vsc_write(mac->adapter, REG_ING_FFILT_MASK0,
393		  0xffff0000 | (addr[4] << 8) | addr[5]);
394	vsc_write(mac->adapter, REG_ING_FFILT_MASK1,
395		  0xffff0000 | (addr[2] << 8) | addr[3]);
396	vsc_write(mac->adapter, REG_ING_FFILT_MASK2,
397		  0xffff0000 | (addr[0] << 8) | addr[1]);
398	return 0;
399}
400
401static int mac_get_address(struct cmac *mac, u8 addr[6])
402{
403	u32 addr_lo, addr_hi;
404	int port = mac->instance->index;
405
406	vsc_read(mac->adapter, REG_MAC_LOW_ADDR(port), &addr_lo);
407	vsc_read(mac->adapter, REG_MAC_HIGH_ADDR(port), &addr_hi);
408
409	addr[0] = (u8) (addr_hi >> 16);
410	addr[1] = (u8) (addr_hi >> 8);
411	addr[2] = (u8) addr_hi;
412	addr[3] = (u8) (addr_lo >> 16);
413	addr[4] = (u8) (addr_lo >> 8);
414	addr[5] = (u8) addr_lo;
415	return 0;
416}
417
418/* This is intended to reset a port, not the whole MAC */
419static int mac_reset(struct cmac *mac)
420{
421	int index = mac->instance->index;
422
423	run_table(mac->adapter, vsc7326_portinit[index],
424		  ARRAY_SIZE(vsc7326_portinit[index]));
425
426	return 0;
427}
428
429static int mac_set_rx_mode(struct cmac *mac, struct t1_rx_mode *rm)
430{
431	u32 v;
432	int port = mac->instance->index;
433
434	vsc_read(mac->adapter, REG_ING_FFILT_UM_EN, &v);
435	v |= 1 << 12;
436
437	if (t1_rx_mode_promisc(rm))
438		v &= ~(1 << (port + 16));
439	else
440		v |= 1 << (port + 16);
441
442	vsc_write(mac->adapter, REG_ING_FFILT_UM_EN, v);
443	return 0;
444}
445
446static int mac_set_mtu(struct cmac *mac, int mtu)
447{
448	int port = mac->instance->index;
449
450	if (mtu > MAX_MTU)
451		return -EINVAL;
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
458static 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
527static 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
544static 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 sofware counters */
565	memset(&mac->stats, 0, sizeof(struct cmac_statistics));
566
567	return 0;
568}
569
570static 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
585static 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 */
638static 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
659static void mac_destroy(struct cmac *mac)
660{
661	kfree(mac);
662}
663
664static 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
681static 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
713static 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
721const struct gmac t1_vsc7326_ops = {
722	.stats_update_period = STATS_TICK_SECS,
723	.create              = vsc7326_mac_create,
724	.reset               = vsc7326_mac_reset,
725};
726