Esempio n. 1
0
/*
 * Marvell 88E61XX Switch initialization
 */
int mv88e61xx_switch_initialize(struct mv88e61xx_config *swconfig)
{
	u32 prt;
	u16 reg;
	char *idstr;
	char *name = swconfig->name;
	int time;

	if (miiphy_set_current_dev(name)) {
		printf("%s failed\n", __FUNCTION__);
		return -1;
	}

	if (!(swconfig->cpuport & ((1 << 4) | (1 << 5)))) {
		swconfig->cpuport = (1 << 5);
		printf("Invalid cpu port config, using default port5\n");
	}

	RD_SWITCH_PORT_REG(name, 0, MII_PHYSID2, &reg);
	switch (reg &= 0xfff0) {
	case 0x1610:
		idstr = "88E6161";
		break;
	case 0x1650:
		idstr = "88E6165";
		break;
	case 0x1210:
		idstr = "88E6123";
		/* ports 2,3,4 not available */
		swconfig->ports_enabled &= 0x023;
		break;
	default:
		/* Could not detect switch id */
		idstr = "88E61??";
		break;
	}

	/* be sure all ports are disabled */
	for (prt = 0; prt < MV88E61XX_MAX_PORTS_NUM; prt++) {
		RD_SWITCH_PORT_REG(name, prt, MV88E61XX_PRT_CTRL_REG, &reg);
		reg &= ~0x3;
		WR_SWITCH_PORT_REG(name, prt, MV88E61XX_PRT_CTRL_REG, reg);
	}

	/* wait 2 ms for queues to drain */
	udelay(2000);

	/* reset switch */
	RD_SWITCH_REG(name, MV88E61XX_GLBREG_DEVADR, MV88E61XX_SGCR, &reg);
	reg |= 0x8000;
	WR_SWITCH_REG(name, MV88E61XX_GLBREG_DEVADR, MV88E61XX_SGCR, reg);

	/* wait up to 1 second for switch reset complete */
	for (time = 1000; time; time--) {
		RD_SWITCH_REG(name, MV88E61XX_GLBREG_DEVADR, MV88E61XX_SGSR,
			&reg);
		if ((reg & 0xc800) == 0xc800)
			break;
		udelay(1000);
	}
	if (!time)
		return -1;

	/* Port based VLANs configuration */
	mv88e61xx_port_vlan_config(swconfig);

	if (swconfig->rgmii_delay == MV88E61XX_RGMII_DELAY_EN) {
		/*
		 * Enable RGMII delay on Tx and Rx for CPU port
		 * Ref: sec 9.5 of chip datasheet-02
		 */
		/*Force port link down */
		WR_SWITCH_PORT_REG(name, 5, MV88E61XX_PCS_CTRL_REG, 0x10);
		/* configure port RGMII delay */
		WR_SWITCH_PORT_REG(name, 4,
			MV88E61XX_RGMII_TIMECTRL_REG, 0x81e7);
		RD_SWITCH_PORT_REG(name, 5,
			MV88E61XX_RGMII_TIMECTRL_REG, &reg);
		WR_SWITCH_PORT_REG(name, 5,
			MV88E61XX_RGMII_TIMECTRL_REG, reg | 0x18);
		WR_SWITCH_PORT_REG(name, 4,
			MV88E61XX_RGMII_TIMECTRL_REG, 0xc1e7);
		/* Force port to RGMII FDX 1000Base then up */
		WR_SWITCH_PORT_REG(name, 5, MV88E61XX_PCS_CTRL_REG, 0x1e);
		WR_SWITCH_PORT_REG(name, 5, MV88E61XX_PCS_CTRL_REG, 0x3e);
	}

	for (prt = 0; prt < MV88E61XX_MAX_PORTS_NUM; prt++) {

		/* configure port's PHY */
		if (!((1 << prt) & swconfig->cpuport)) {
			/* port 4 has phy 6, not 4 */
			int phy = (prt == 4) ? 6 : prt;
			if (mv88361xx_powerup(swconfig, phy))
				return -1;
			if (mv88361xx_reverse_mdipn(swconfig, phy))
				return -1;
			if (mv88361xx_led_init(swconfig, phy))
				return -1;
		}

		/* set port VID to port+1 except for cpu port */
		if (!((1 << prt) & swconfig->cpuport)) {
			RD_SWITCH_PORT_REG(name, prt,
				MV88E61XX_PRT_VID_REG, &reg);
			WR_SWITCH_PORT_REG(name, prt,
				MV88E61XX_PRT_VID_REG,
				(reg & ~1023) | (prt+1));
		}

		/*Program port state */
		RD_SWITCH_PORT_REG(name, prt,
			MV88E61XX_PRT_CTRL_REG, &reg);
		WR_SWITCH_PORT_REG(name, prt,
			MV88E61XX_PRT_CTRL_REG,
			reg | (swconfig->portstate & 0x03));

	}

	printf("%s Initialized on %s\n", idstr, name);
	return 0;
}
Esempio n. 2
0
/*
 * Marvell 88E61XX Switch initialization
 */
int mv88e61xx_switch_initialize(struct mv88e61xx_config *swconfig)
{
	u32 prt;
	u16 reg;
	char *idstr;
	char *name = swconfig->name;

	if (miiphy_set_current_dev(name)) {
		printf("%s failed\n", __FUNCTION__);
		return -1;
	}

	if (!(swconfig->cpuport & ((1 << 4) | (1 << 5)))) {
		swconfig->cpuport = (1 << 5);
		printf("Invalid cpu port config, using default port5\n");
	}

	RD_PHY(name, MV88E61XX_PRT_OFST, PHY_PHYIDR2, &reg);
	reg &= 0xfff0;
	if (reg == 0x1610)
		idstr = "88E6161";
	if (reg == 0x1650)
		idstr = "88E6165";
	if (reg == 0x1210) {
		idstr = "88E6123";
		/* ports 2,3,4 not available */
		swconfig->ports_enabled &= 0x023;
	}

	/* Port based VLANs configuration */
	if ((swconfig->vlancfg == MV88E61XX_VLANCFG_DEFAULT)
	    || (swconfig->vlancfg == MV88E61XX_VLANCFG_ROUTER))
		mv88e61xx_port_vlan_config(swconfig, MV88E61XX_MAX_PORTS_NUM,
					   MV88E61XX_PRT_OFST);
	else {
		printf("Unsupported mode %s failed\n", __FUNCTION__);
		return -1;
	}

	if (swconfig->rgmii_delay == MV88E61XX_RGMII_DELAY_EN) {
		/*
		 * Enable RGMII delay on Tx and Rx for CPU port
		 * Ref: sec 9.5 of chip datasheet-02
		 */
		WR_PHY(name, MV88E61XX_PRT_OFST + 5,
		       MV88E61XX_RGMII_TIMECTRL_REG, 0x18);
		WR_PHY(name, MV88E61XX_PRT_OFST + 4,
		       MV88E61XX_RGMII_TIMECTRL_REG, 0xc1e7);
	}

	for (prt = 0; prt < MV88E61XX_MAX_PORTS_NUM; prt++) {
		if (!((1 << prt) & swconfig->cpuport)) {

			if (mv88361xx_led_init(swconfig, prt))
				return -1;
			if (mv88361xx_reverse_mdipn(swconfig, prt))
				return -1;
			if (mv88361xx_powerup(swconfig, prt))
				return -1;
		}

		/*Program port state */
		RD_PHY(name, MV88E61XX_PRT_OFST + prt,
		       MV88E61XX_PRT_CTRL_REG, &reg);
		WR_PHY(name, MV88E61XX_PRT_OFST + prt,
		       MV88E61XX_PRT_CTRL_REG,
		       reg | (swconfig->portstate & 0x03));
	}

	printf("%s Initialized on %s\n", idstr, name);
	return 0;
}