/**
 * cvm_oct_phy_setup_device - setup the PHY
 *
 * @dev:    Device to setup
 *
 * Returns Zero on success, negative on failure
 */
int cvm_oct_phy_setup_device(struct net_device *dev)
{
	struct octeon_ethernet *priv = netdev_priv(dev);

	int phy_addr = cvmx_helper_board_get_mii_address(priv->port);
	if (phy_addr != -1) {
		char phy_id[20];

		if (phy_addr & 0x100)
			snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT, "1", phy_addr & 0xff);
		else
			snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT, "0", phy_addr);

		priv->phydev = phy_connect(dev, phy_id, cvm_oct_adjust_link, 0,
					   PHY_INTERFACE_MODE_GMII);

		if (IS_ERR(priv->phydev)) {
			priv->phydev = NULL;
			return -1;
		}
		priv->last_link = 0;
		phy_start_aneg(priv->phydev);
	}
	return 0;
}
Exemple #2
0
/**
 * Setup the MDIO device structures
 *
 * @param dev    Device to setup
 *
 * @return Zero on success, negative on failure
 */
int cvm_oct_mdio_setup_device(struct ifnet *ifp)
{
	cvm_oct_private_t *priv = (cvm_oct_private_t *)ifp->if_softc;

	priv->phy_id = cvmx_helper_board_get_mii_address(priv->port);
	priv->phy_device = NULL;
	priv->mdio_read = NULL;
	priv->mdio_write = NULL;

	return 0;
}
Exemple #3
0
int cvm_oct_mdio_setup_device(struct net_device *dev)
{
	struct octeon_ethernet *priv = netdev_priv(dev);
	int phy_id = cvmx_helper_board_get_mii_address(priv->port);
	if (phy_id != -1) {
		priv->mii_info.dev = dev;
		priv->mii_info.phy_id = phy_id;
		priv->mii_info.phy_id_mask = 0xff;
		priv->mii_info.supports_gmii = 1;
		priv->mii_info.reg_num_mask = 0x1f;
		priv->mii_info.mdio_read = cvm_oct_mdio_read;
		priv->mii_info.mdio_write = cvm_oct_mdio_write;
	} else {
		
		priv->mii_info.mdio_read = cvm_oct_mdio_dummy_read;
		priv->mii_info.mdio_write = cvm_oct_mdio_dummy_write;
	}
	return 0;
}
/**
 * This function is the board specific method of determining an
 * ethernet ports link speed. Most Octeon boards have Marvell PHYs
 * and are handled by the fall through case. This function must be
 * updated for boards that don't have the normal Marvell PHYs.
 *
 * This function must be modified for every new Octeon board.
 * Internally it uses switch statements based on the cvmx_sysinfo
 * data to determine board types and revisions. It relies on the
 * fact that every Octeon board receives a unique board type
 * enumeration from the bootloader.
 *
 * @ipd_port: IPD input port associated with the port we want to get link
 *                 status for.
 *
 * Returns The ports link status. If the link isn't fully resolved, this must
 *         return zero.
 */
cvmx_helper_link_info_t __cvmx_helper_board_link_get(int ipd_port)
{
	cvmx_helper_link_info_t result;
	int phy_addr;
	int is_broadcom_phy = 0;

	/* Give the user a chance to override the processing of this function */
	if (cvmx_override_board_link_get)
		return cvmx_override_board_link_get(ipd_port);

	/* Unless we fix it later, all links are defaulted to down */
	result.u64 = 0;

	/*
	 * This switch statement should handle all ports that either don't use
	 * Marvell PHYS, or don't support in-band status.
	 */
	switch (cvmx_sysinfo_get()->board_type) {
	case CVMX_BOARD_TYPE_SIM:
		/* The simulator gives you a simulated 1Gbps full duplex link */
		result.s.link_up = 1;
		result.s.full_duplex = 1;
		result.s.speed = 1000;
		return result;
	case CVMX_BOARD_TYPE_EBH3100:
	case CVMX_BOARD_TYPE_CN3010_EVB_HS5:
	case CVMX_BOARD_TYPE_CN3005_EVB_HS5:
	case CVMX_BOARD_TYPE_CN3020_EVB_HS5:
		/* Port 1 on these boards is always Gigabit */
		if (ipd_port == 1) {
			result.s.link_up = 1;
			result.s.full_duplex = 1;
			result.s.speed = 1000;
			return result;
		}
		/* Fall through to the generic code below */
		break;
	case CVMX_BOARD_TYPE_CUST_NB5:
		/* Port 1 on these boards is always Gigabit */
		if (ipd_port == 1) {
			result.s.link_up = 1;
			result.s.full_duplex = 1;
			result.s.speed = 1000;
			return result;
		} else		/* The other port uses a broadcom PHY */
			is_broadcom_phy = 1;
		break;
	case CVMX_BOARD_TYPE_BBGW_REF:
		/* Port 1 on these boards is always Gigabit */
		if (ipd_port == 2) {
			/* Port 2 is not hooked up */
			result.u64 = 0;
			return result;
		} else {
			/* Ports 0 and 1 connect to the switch */
			result.s.link_up = 1;
			result.s.full_duplex = 1;
			result.s.speed = 1000;
			return result;
		}
		break;
	}

	phy_addr = cvmx_helper_board_get_mii_address(ipd_port);
	if (phy_addr != -1) {
		if (is_broadcom_phy) {
			/*
			 * Below we are going to read SMI/MDIO
			 * register 0x19 which works on Broadcom
			 * parts
			 */
			int phy_status =
			    cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff,
					   0x19);
			switch ((phy_status >> 8) & 0x7) {
			case 0:
				result.u64 = 0;
				break;
			case 1:
				result.s.link_up = 1;
				result.s.full_duplex = 0;
				result.s.speed = 10;
				break;
			case 2:
				result.s.link_up = 1;
				result.s.full_duplex = 1;
				result.s.speed = 10;
				break;
			case 3:
				result.s.link_up = 1;
				result.s.full_duplex = 0;
				result.s.speed = 100;
				break;
			case 4:
				result.s.link_up = 1;
				result.s.full_duplex = 1;
				result.s.speed = 100;
				break;
			case 5:
				result.s.link_up = 1;
				result.s.full_duplex = 1;
				result.s.speed = 100;
				break;
			case 6:
				result.s.link_up = 1;
				result.s.full_duplex = 0;
				result.s.speed = 1000;
				break;
			case 7:
				result.s.link_up = 1;
				result.s.full_duplex = 1;
				result.s.speed = 1000;
				break;
			}
		} else {
			/*
			 * This code assumes we are using a Marvell
			 * Gigabit PHY. All the speed information can
			 * be read from register 17 in one
			 * go. Somebody using a different PHY will
			 * need to handle it above in the board
			 * specific area.
			 */
			int phy_status =
			    cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, 17);

			/*
			 * If the resolve bit 11 isn't set, see if
			 * autoneg is turned off (bit 12, reg 0). The
			 * resolve bit doesn't get set properly when
			 * autoneg is off, so force it.
			 */
			if ((phy_status & (1 << 11)) == 0) {
				int auto_status =
				    cvmx_mdio_read(phy_addr >> 8,
						   phy_addr & 0xff, 0);
				if ((auto_status & (1 << 12)) == 0)
					phy_status |= 1 << 11;
			}

			/*
			 * Only return a link if the PHY has finished
			 * auto negotiation and set the resolved bit
			 * (bit 11)
			 */
			if (phy_status & (1 << 11)) {
				result.s.link_up = 1;
				result.s.full_duplex = ((phy_status >> 13) & 1);
				switch ((phy_status >> 14) & 3) {
				case 0:	/* 10 Mbps */
					result.s.speed = 10;
					break;
				case 1:	/* 100 Mbps */
					result.s.speed = 100;
					break;
				case 2:	/* 1 Gbps */
					result.s.speed = 1000;
					break;
				case 3:	/* Illegal */
					result.u64 = 0;
					break;
				}
			}