PageRenderTime 76ms CodeModel.GetById 17ms app.highlight 52ms RepoModel.GetById 2ms app.codeStats 0ms

/drivers/net/ethernet/chelsio/cxgb/vsc7326.c

http://github.com/mirrors/linux
C | 726 lines | 579 code | 101 blank | 46 comment | 86 complexity | dee832a03b01cc9fe28636ef3ea88371 MD5 | raw file
  1// SPDX-License-Identifier: GPL-2.0
  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
 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)
 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	/* 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);
 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	/* 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);
 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 );
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	/*run bist*/
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	/*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)
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	/*enable mem*/
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/* 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
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
565	/* Clear software counters */
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		/* 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);
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 * 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
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};