| /* | 
 |  * (C) Copyright 2004 | 
 |  * Elmeg Communications Systems GmbH, Juergen Selent (j.selent@elmeg.de) | 
 |  * | 
 |  * Support for the Elmeg VoVPN Gateway Module | 
 |  * ------------------------------------------ | 
 |  * Initialize Marvell M88E6060 Switch | 
 |  * | 
 |  * This program is free software; you can redistribute it and/or | 
 |  * modify it under the terms of the GNU General Public License as | 
 |  * published by the Free Software Foundation; either version 2 of | 
 |  * the License, or (at your option) any later version. | 
 |  * | 
 |  * This program is distributed in the hope that it will be useful, | 
 |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
 |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
 |  * GNU General Public License for more details. | 
 |  * | 
 |  * You should have received a copy of the GNU General Public License | 
 |  * along with this program; if not, write to the Free Software | 
 |  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | 
 |  * MA 02111-1307 USA | 
 |  */ | 
 |  | 
 | #include <common.h> | 
 | #include <ioports.h> | 
 | #include <mpc8260.h> | 
 | #include <asm/m8260_pci.h> | 
 | #include <net.h> | 
 | #include <miiphy.h> | 
 |  | 
 | #include "m88e6060.h" | 
 |  | 
 | #if defined(CONFIG_CMD_NET) | 
 | static int		prtTab[M88X_PRT_CNT] = { 8, 9, 10, 11, 12, 13 }; | 
 | static int		phyTab[M88X_PHY_CNT] = { 0, 1, 2, 3, 4 }; | 
 |  | 
 | static m88x_regCfg_t	prtCfg0[] = { | 
 | 	{  4, 0x3e7c, 0x8000 }, | 
 | 	{  4, 0x3e7c, 0x8003 }, | 
 | 	{  6, 0x0fc0, 0x001e }, | 
 | 	{ -1, 0xffff, 0x0000 } | 
 | }; | 
 |  | 
 | static m88x_regCfg_t	prtCfg1[] = { | 
 | 	{  4, 0x3e7c, 0x8000 }, | 
 | 	{  4, 0x3e7c, 0x8003 }, | 
 | 	{  6, 0x0fc0, 0x001d }, | 
 | 	{ -1, 0xffff, 0x0000 } | 
 | }; | 
 |  | 
 | static m88x_regCfg_t	prtCfg2[] = { | 
 | 	{  4, 0x3e7c, 0x8000 }, | 
 | 	{  4, 0x3e7c, 0x8003 }, | 
 | 	{  6, 0x0fc0, 0x001b }, | 
 | 	{ -1, 0xffff, 0x0000 } | 
 | }; | 
 |  | 
 | static m88x_regCfg_t	prtCfg3[] = { | 
 | 	{  4, 0x3e7c, 0x8000 }, | 
 | 	{  4, 0x3e7c, 0x8003 }, | 
 | 	{  6, 0x0fc0, 0x0017 }, | 
 | 	{ -1, 0xffff, 0x0000 } | 
 | }; | 
 |  | 
 | static m88x_regCfg_t	prtCfg4[] = { | 
 | 	{  4, 0x3e7c, 0x8000 }, | 
 | 	{  4, 0x3e7c, 0x8003 }, | 
 | 	{  6, 0x0fc0, 0x000f }, | 
 | 	{ -1, 0xffff, 0x0000 } | 
 | }; | 
 |  | 
 | static m88x_regCfg_t	*prtCfg[M88X_PRT_CNT] = { | 
 | 	prtCfg0,prtCfg1,prtCfg2,prtCfg3,prtCfg4,NULL | 
 | }; | 
 |  | 
 | static m88x_regCfg_t	phyCfgX[] = { | 
 | 	{  4, 0xfa1f, 0x01e0 }, | 
 | 	{  0, 0x213f, 0x1200 }, | 
 | 	{ 24, 0x81ff, 0x1200 }, | 
 | 	{ -1, 0xffff, 0x0000 } | 
 | }; | 
 |  | 
 | static m88x_regCfg_t	*phyCfg[M88X_PHY_CNT] = { | 
 | 	phyCfgX,phyCfgX,phyCfgX,phyCfgX,NULL | 
 | }; | 
 |  | 
 | #if 0 | 
 | static void | 
 | m88e6060_dump( int devAddr ) | 
 | { | 
 | 	int		i, j; | 
 | 	unsigned short	val[6]; | 
 |  | 
 | 	printf( "M88E6060 Register Dump\n" ); | 
 | 	printf( "====================================\n" ); | 
 | 	printf( "PortNo    0    1    2    3    4    5\n" ); | 
 | 	for (i=0; i<6; i++) | 
 | 		miiphy_read( devAddr+prtTab[i],M88X_PRT_STAT,&val[i] ); | 
 | 	printf( "STAT   %04hx %04hx %04hx %04hx %04hx %04hx\n", | 
 | 		val[0],val[1],val[2],val[3],val[4],val[5] ); | 
 |  | 
 | 	for (i=0; i<6; i++) | 
 | 		miiphy_read( devAddr+prtTab[i],M88X_PRT_ID,&val[i] ); | 
 | 	printf( "ID     %04hx %04hx %04hx %04hx %04hx %04hx\n", | 
 | 		val[0],val[1],val[2],val[3],val[4],val[5] ); | 
 |  | 
 | 	for (i=0; i<6; i++) | 
 | 		miiphy_read( devAddr+prtTab[i],M88X_PRT_CNTL,&val[i] ); | 
 | 	printf( "CNTL   %04hx %04hx %04hx %04hx %04hx %04hx\n", | 
 | 		val[0],val[1],val[2],val[3],val[4],val[5] ); | 
 |  | 
 | 	for (i=0; i<6; i++) | 
 | 		miiphy_read( devAddr+prtTab[i],M88X_PRT_VLAN,&val[i] ); | 
 | 	printf( "VLAN   %04hx %04hx %04hx %04hx %04hx %04hx\n", | 
 | 		val[0],val[1],val[2],val[3],val[4],val[5] ); | 
 |  | 
 | 	for (i=0; i<6; i++) | 
 | 		miiphy_read( devAddr+prtTab[i],M88X_PRT_PAV,&val[i] ); | 
 | 	printf( "PAV    %04hx %04hx %04hx %04hx %04hx %04hx\n", | 
 | 		val[0],val[1],val[2],val[3],val[4],val[5] ); | 
 |  | 
 | 	for (i=0; i<6; i++) | 
 | 		miiphy_read( devAddr+prtTab[i],M88X_PRT_RX,&val[i] ); | 
 | 	printf( "RX     %04hx %04hx %04hx %04hx %04hx %04hx\n", | 
 | 		val[0],val[1],val[2],val[3],val[4],val[5] ); | 
 |  | 
 | 	for (i=0; i<6; i++) | 
 | 		miiphy_read( devAddr+prtTab[i],M88X_PRT_TX,&val[i] ); | 
 | 	printf( "TX     %04hx %04hx %04hx %04hx %04hx %04hx\n", | 
 | 		val[0],val[1],val[2],val[3],val[4],val[5] ); | 
 |  | 
 | 	printf( "------------------------------------\n" ); | 
 | 	printf( "PhyNo     0    1    2    3    4\n" ); | 
 | 	for (i=0; i<9; i++) { | 
 | 		for (j=0; j<5; j++) { | 
 | 			miiphy_read( devAddr+phyTab[j],i,&val[j] ); | 
 | 		} | 
 | 		printf( "0x%02x   %04hx %04hx %04hx %04hx %04hx\n", | 
 | 			i,val[0],val[1],val[2],val[3],val[4] ); | 
 | 	} | 
 | 	for (i=0x10; i<0x1d; i++) { | 
 | 		for (j=0; j<5; j++) { | 
 | 			miiphy_read( devAddr+phyTab[j],i,&val[j] ); | 
 | 		} | 
 | 		printf( "0x%02x   %04hx %04hx %04hx %04hx %04hx\n", | 
 | 			i,val[0],val[1],val[2],val[3],val[4] ); | 
 | 	} | 
 | } | 
 | #endif | 
 |  | 
 | int | 
 | m88e6060_initialize( int devAddr ) | 
 | { | 
 | 	static char	*_f = "m88e6060_initialize:"; | 
 | 	m88x_regCfg_t	*p; | 
 | 	int		err; | 
 | 	int		i; | 
 | 	unsigned short	val; | 
 |  | 
 | 	/*** reset all phys into powerdown ************************************/ | 
 | 	for (i=0, err=0; i<M88X_PHY_CNT; i++) { | 
 | 		err += bb_miiphy_read(NULL, devAddr+phyTab[i],M88X_PHY_CNTL,&val ); | 
 | 		/* keep SpeedLSB, Duplex */ | 
 | 		val &= 0x2100; | 
 | 		/* set SWReset, AnegEn, PwrDwn, RestartAneg */ | 
 | 		val |= 0x9a00; | 
 | 		err += bb_miiphy_write(NULL, devAddr+phyTab[i],M88X_PHY_CNTL,val ); | 
 | 	} | 
 | 	if (err) { | 
 | 		printf( "%s [ERR] reset phys\n",_f ); | 
 | 		return( -1 ); | 
 | 	} | 
 |  | 
 | 	/*** disable all ports ************************************************/ | 
 | 	for (i=0, err=0; i<M88X_PRT_CNT; i++) { | 
 | 		err += bb_miiphy_read(NULL, devAddr+prtTab[i],M88X_PRT_CNTL,&val ); | 
 | 		val &= 0xfffc; | 
 | 		err += bb_miiphy_write(NULL, devAddr+prtTab[i],M88X_PRT_CNTL,val ); | 
 | 	} | 
 | 	if (err) { | 
 | 		printf( "%s [ERR] disable ports\n",_f ); | 
 | 		return( -1 ); | 
 | 	} | 
 |  | 
 | 	/*** initialize switch ************************************************/ | 
 | 	/* set switch mac addr */ | 
 | #define ea eth_get_dev()->enetaddr | 
 | 	val = (ea[4] <<  8) | ea[5]; | 
 | 	err = bb_miiphy_write(NULL, devAddr+15,M88X_GLB_MAC45,val ); | 
 | 	val = (ea[2] <<  8) | ea[3]; | 
 | 	err += bb_miiphy_write(NULL, devAddr+15,M88X_GLB_MAC23,val ); | 
 | 	val = (ea[0] <<  8) | ea[1]; | 
 | #undef ea | 
 | 	val &= 0xfeff;		/* clear DiffAddr */ | 
 | 	err += bb_miiphy_write(NULL, devAddr+15,M88X_GLB_MAC01,val ); | 
 | 	if (err) { | 
 | 		printf( "%s [ERR] switch mac address register\n",_f ); | 
 | 		return( -1 ); | 
 | 	} | 
 |  | 
 | 	/* !DiscardExcessive, MaxFrameSize, CtrMode */ | 
 | 	err = bb_miiphy_read(NULL, devAddr+15,M88X_GLB_CNTL,&val ); | 
 | 	val &= 0xd870; | 
 | 	val |= 0x0500; | 
 | 	err += bb_miiphy_write(NULL, devAddr+15,M88X_GLB_CNTL,val ); | 
 | 	if (err) { | 
 | 		printf( "%s [ERR] switch global control register\n",_f ); | 
 | 		return( -1 ); | 
 | 	} | 
 |  | 
 | 	/* LernDis off, ATUSize 1024, AgeTime 5min */ | 
 | 	err = bb_miiphy_read(NULL, devAddr+15,M88X_ATU_CNTL,&val ); | 
 | 	val &= 0x000f; | 
 | 	val |= 0x2130; | 
 | 	err += bb_miiphy_write(NULL, devAddr+15,M88X_ATU_CNTL,val ); | 
 | 	if (err) { | 
 | 		printf( "%s [ERR] atu control register\n",_f ); | 
 | 		return( -1 ); | 
 | 	} | 
 |  | 
 | 	/*** initialize ports *************************************************/ | 
 | 	for (i=0; i<M88X_PRT_CNT; i++) { | 
 | 		if ((p = prtCfg[i]) == NULL) { | 
 | 			continue; | 
 | 		} | 
 | 		while (p->reg != -1) { | 
 | 			err = 0; | 
 | 			err += bb_miiphy_read(NULL, devAddr+prtTab[i],p->reg,&val ); | 
 | 			val &= p->msk; | 
 | 			val |= p->val; | 
 | 			err += bb_miiphy_write(NULL, devAddr+prtTab[i],p->reg,val ); | 
 | 			if (err) { | 
 | 				printf( "%s [ERR] config port %d register %d\n",_f,i,p->reg ); | 
 | 				/* XXX what todo */ | 
 | 			} | 
 | 			p++; | 
 | 		} | 
 | 	} | 
 |  | 
 | 	/*** initialize phys **************************************************/ | 
 | 	for (i=0; i<M88X_PHY_CNT; i++) { | 
 | 		if ((p = phyCfg[i]) == NULL) { | 
 | 			continue; | 
 | 		} | 
 | 		while (p->reg != -1) { | 
 | 			err = 0; | 
 | 			err += bb_miiphy_read(NULL, devAddr+phyTab[i],p->reg,&val ); | 
 | 			val &= p->msk; | 
 | 			val |= p->val; | 
 | 			err += bb_miiphy_write(NULL, devAddr+phyTab[i],p->reg,val ); | 
 | 			if (err) { | 
 | 				printf( "%s [ERR] config phy %d register %d\n",_f,i,p->reg ); | 
 | 				/* XXX what todo */ | 
 | 			} | 
 | 			p++; | 
 | 		} | 
 | 	} | 
 | 	udelay(100000); | 
 | 	return( 0 ); | 
 | } | 
 | #endif |