예제 #1
0
파일: ethernet_phy.c 프로젝트: unnamet/Repo
/**
 * \brief Get the Link & speed settings, and automatically set up the GMAC with the
 * settings.
 *
 * \param p_gmac   Pointer to the GMAC instance.
 * \param uc_phy_addr PHY address.
 * \param uc_apply_setting_flag Set to 0 to not apply the PHY configurations, else to apply.
 *
 * Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.
 */
uint8_t ethernet_phy_set_link(Gmac *p_gmac, uint8_t uc_phy_addr,
		uint8_t uc_apply_setting_flag)
{
	uint32_t ul_stat1;
	uint32_t ul_stat2;
	uint8_t uc_phy_address, uc_speed = true, uc_fd = true;
	uint8_t uc_rc = GMAC_TIMEOUT;

	gmac_enable_management(p_gmac, true);

	uc_phy_address = uc_phy_addr;

	uc_rc = gmac_phy_read(p_gmac, uc_phy_address, GMII_BMSR, &ul_stat1);
	if (uc_rc != GMAC_OK) {
		/* Disable PHY management and start the GMAC transfer */
		gmac_enable_management(p_gmac, false);

		return uc_rc;
	}
	if ((ul_stat1 & GMII_LINK_STATUS) == 0) {
		/* Disable PHY management and start the GMAC transfer */
		gmac_enable_management(p_gmac, false);

		return GMAC_INVALID;
	}

	if (uc_apply_setting_flag == 0) {
		/* Disable PHY management and start the GMAC transfer */
		gmac_enable_management(p_gmac, false);

		return uc_rc;
	}

	/* Read advertisement */
	uc_rc = gmac_phy_read(p_gmac, uc_phy_address, GMII_ANAR, &ul_stat2);
phy_props.phy_stat1 = ul_stat1;
phy_props.phy_stat2 = ul_stat2;
	if (uc_rc != GMAC_OK) {
		/* Disable PHY management and start the GMAC transfer */
		gmac_enable_management(p_gmac, false);

		return uc_rc;
	}

	if ((ul_stat1 & GMII_100BASE_TX_FD) && (ul_stat2 & GMII_100TX_FDX)) {
		/* Set GMAC for 100BaseTX and Full Duplex */
		uc_speed = true;
		uc_fd = true;
	} else
	if ((ul_stat1 & GMII_100BASE_T4_HD) && (ul_stat2 & GMII_100TX_HDX)) {
		/* Set MII for 100BaseTX and Half Duplex */
		uc_speed = true;
		uc_fd = false;
	} else
	if ((ul_stat1 & GMII_10BASE_T_FD) && (ul_stat2 & GMII_10_FDX)) {
		/* Set MII for 10BaseT and Full Duplex */
		uc_speed = false;
		uc_fd = true;
	} else
	if ((ul_stat1 & GMII_10BASE_T_HD) && (ul_stat2 & GMII_10_HDX)) {
		/* Set MII for 10BaseT and Half Duplex */
		uc_speed = false;
		uc_fd = false;
	}

	gmac_set_speed(p_gmac, uc_speed);
	gmac_enable_full_duplex(p_gmac, uc_fd);

	/* Start the GMAC transfers */
	gmac_enable_management(p_gmac, false);
	return uc_rc;
}
예제 #2
0
파일: ethernet_phy.c 프로젝트: unnamet/Repo
/**
 * \brief Issue an auto negotiation of the PHY.
 *
 * \param p_gmac   Pointer to the GMAC instance.
 * \param uc_phy_addr PHY address.
 *
 * Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.
 */
uint8_t ethernet_phy_auto_negotiate(Gmac *p_gmac, uint8_t uc_phy_addr)
{
	uint32_t ul_retry_max = ETH_PHY_RETRY_MAX;
	uint32_t ul_value;
	uint32_t ul_phy_anar;
	uint32_t ul_retry_count = 0;
	uint8_t uc_speed = 0;
	uint8_t uc_fd=0;
	uint8_t uc_rc = GMAC_TIMEOUT;

	gmac_enable_management(p_gmac, true);

	/* Set up control register */
	uc_rc = gmac_phy_read(p_gmac, uc_phy_addr, GMII_BMCR, &ul_value);
	if (uc_rc != GMAC_OK) {
		gmac_enable_management(p_gmac, false);
phy_props.phy_result = -1;
		return uc_rc;
	}

	ul_value &= ~(uint32_t)GMII_AUTONEG; /* Remove auto-negotiation enable */
	ul_value &= ~(uint32_t)(GMII_LOOPBACK | GMII_POWER_DOWN);
	ul_value |= (uint32_t)GMII_ISOLATE; /* Electrically isolate PHY */
	uc_rc = gmac_phy_write(p_gmac, uc_phy_addr, GMII_BMCR, ul_value);
	if (uc_rc != GMAC_OK) {
		gmac_enable_management(p_gmac, false);
phy_props.phy_result = -2;
		return uc_rc;
	}

	/*
	 * Set the Auto_negotiation Advertisement Register.
	 * MII advertising for Next page.
	 * 100BaseTxFD and HD, 10BaseTFD and HD, IEEE 802.3.
	 */
	ul_phy_anar = GMII_100TX_FDX | GMII_100TX_HDX | GMII_10_FDX | GMII_10_HDX |
			GMII_AN_IEEE_802_3;
	uc_rc = gmac_phy_write(p_gmac, uc_phy_addr, GMII_ANAR, ul_phy_anar);
	if (uc_rc != GMAC_OK) {
		gmac_enable_management(p_gmac, false);
phy_props.phy_result = -3;
		return uc_rc;
	}

	/* Read & modify control register */
	uc_rc = gmac_phy_read(p_gmac, uc_phy_addr, GMII_BMCR, &ul_value);
	if (uc_rc != GMAC_OK) {
		gmac_enable_management(p_gmac, false);
phy_props.phy_result = -4;
		return uc_rc;
	}

	ul_value |= GMII_SPEED_SELECT | GMII_AUTONEG | GMII_DUPLEX_MODE;
	uc_rc = gmac_phy_write(p_gmac, uc_phy_addr, GMII_BMCR, ul_value);
	if (uc_rc != GMAC_OK) {
		gmac_enable_management(p_gmac, false);
phy_props.phy_result = -5;
		return uc_rc;
	}

	/* Restart auto negotiation */
	ul_value |= (uint32_t)GMII_RESTART_AUTONEG;
	ul_value &= ~(uint32_t)GMII_ISOLATE;
	uc_rc = gmac_phy_write(p_gmac, uc_phy_addr, GMII_BMCR, ul_value);
	if (uc_rc != GMAC_OK) {
		gmac_enable_management(p_gmac, false);
phy_props.phy_result = -6;
		return uc_rc;
	}

	/* Check if auto negotiation is completed */
	while (1) {
		uc_rc = gmac_phy_read(p_gmac, uc_phy_addr, GMII_BMSR, &ul_value);
		if (uc_rc != GMAC_OK) {
			gmac_enable_management(p_gmac, false);
phy_props.phy_result = -7;
			return uc_rc;
		}
		/* Done successfully */
		if (ul_value & GMII_AUTONEG_COMP) {
			break;
		}

		/* Timeout check */
		if (ul_retry_max) {
			if (++ul_retry_count >= ul_retry_max) {
				gmac_enable_management(p_gmac, false);
phy_props.phy_result = -8;
				return GMAC_TIMEOUT;
			}
		}
	}

	/* Get the auto negotiate link partner base page */
	uc_rc = gmac_phy_read(p_gmac, uc_phy_addr, GMII_PCR1, &phy_props.phy_params);
	if (uc_rc != GMAC_OK) {
		gmac_enable_management(p_gmac, false);
phy_props.phy_result = -9;
		return uc_rc;
	}


	/* Set up the GMAC link speed */
	if ((ul_phy_anar & phy_props.phy_params) & GMII_100TX_FDX) {
		/* Set MII for 100BaseTX and Full Duplex */
		uc_speed = true;
		uc_fd = true;
	} else if ((ul_phy_anar & phy_props.phy_params) & GMII_10_FDX) {
		/* Set MII for 10BaseT and Full Duplex */
		uc_speed = false;
		uc_fd = true;
	} else if ((ul_phy_anar & phy_props.phy_params) & GMII_100TX_HDX) {
		/* Set MII for 100BaseTX and half Duplex */
		uc_speed = true;
		uc_fd = false;
	} else if ((ul_phy_anar & phy_props.phy_params) & GMII_10_HDX) {
		/* Set MII for 10BaseT and half Duplex */
		uc_speed = false;
		uc_fd = false;
	}

	gmac_set_speed(p_gmac, uc_speed);
	gmac_enable_full_duplex(p_gmac, uc_fd);

	/* Select Media Independent Interface type */
	gmac_select_mii_mode(p_gmac, ETH_PHY_MODE);

	gmac_enable_transmit(GMAC, true);
	gmac_enable_receive(GMAC, true);

	gmac_enable_management(p_gmac, false);
phy_props.phy_result = 1;
	return uc_rc;
}
예제 #3
0
/**
 * \brief Issue an auto negotiation of the PHY.
 *
 * \param p_gmac   Pointer to the GMAC instance.
 * \param uc_phy_addr PHY address.
 *
 * Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.
 */
uint8_t ethernet_phy_auto_negotiate(Gmac *p_gmac, uint8_t uc_phy_addr)
{
	uint32_t ul_value;
	uint32_t ul_phy_anar;
	uint32_t ul_phy_analpar;
	uint8_t uc_speed = 0;
	uint8_t uc_fd=0;
	uint8_t uc_rc;

	if(auto_negotiate_state == AUTO_NEGOTIATE_STATE_START) {
		auto_negotiate_wait_counter = 0;
		gmac_enable_management(p_gmac, true);

		/* Set up control register */
		uc_rc = gmac_phy_read(p_gmac, uc_phy_addr, GMII_BMCR, &ul_value);
		if (uc_rc != GMAC_OK) {
			gmac_enable_management(p_gmac, false);
			return uc_rc;
		}


		ul_value &= ~(uint32_t)GMII_AUTONEG; /* Remove auto-negotiation enable */
		ul_value &= ~(uint32_t)(GMII_LOOPBACK | GMII_POWER_DOWN);
		ul_value |= (uint32_t)GMII_ISOLATE; /* Electrically isolate PHY */
		uc_rc = gmac_phy_write(p_gmac, uc_phy_addr, GMII_BMCR, ul_value);
		if (uc_rc != GMAC_OK) {
			gmac_enable_management(p_gmac, false);
			return uc_rc;
		}

		/*
		 * Set the Auto_negotiation Advertisement Register.
		 * MII advertising for Next page.
		 * 100BaseTxFD and HD, 10BaseTFD and HD, IEEE 802.3.
		 */
		ul_phy_anar = GMII_100TX_FDX | GMII_100TX_HDX | GMII_10_FDX | GMII_10_HDX |
				GMII_AN_IEEE_802_3;
		uc_rc = gmac_phy_write(p_gmac, uc_phy_addr, GMII_ANAR, ul_phy_anar);
		if (uc_rc != GMAC_OK) {
			gmac_enable_management(p_gmac, false);
			return uc_rc;
		}

		/* Read & modify control register */
		uc_rc = gmac_phy_read(p_gmac, uc_phy_addr, GMII_BMCR, &ul_value);
		if (uc_rc != GMAC_OK) {
			gmac_enable_management(p_gmac, false);
			return uc_rc;
		}

		ul_value |= GMII_SPEED_SELECT | GMII_AUTONEG | GMII_DUPLEX_MODE;
		uc_rc = gmac_phy_write(p_gmac, uc_phy_addr, GMII_BMCR, ul_value);
		if (uc_rc != GMAC_OK) {
			gmac_enable_management(p_gmac, false);
			return uc_rc;
		}

		/* Restart auto negotiation */
		ul_value |= (uint32_t)GMII_RESTART_AUTONEG;
		ul_value &= ~(uint32_t)GMII_ISOLATE;
		uc_rc = gmac_phy_write(p_gmac, uc_phy_addr, GMII_BMCR, ul_value);
		if (uc_rc != GMAC_OK) {
			gmac_enable_management(p_gmac, false);
			return uc_rc;
		}

		auto_negotiate_state = AUTO_NEGOTIATE_STATE_WAIT;
	}

	if(auto_negotiate_state == AUTO_NEGOTIATE_STATE_WAIT) {
		uc_rc = gmac_phy_read(p_gmac, uc_phy_addr, GMII_BMSR, &ul_value);
		if (uc_rc != GMAC_OK) {
			gmac_enable_management(p_gmac, false);
			auto_negotiate_state = AUTO_NEGOTIATE_STATE_START;
			return uc_rc;
		}

		// Not done successfully, we will try again later
		if(!(ul_value & GMII_AUTONEG_COMP)) {
			auto_negotiate_wait_counter++;
			// here we will try again later
			if (auto_negotiate_wait_counter >= ETH_PHY_RETRY_MAX) {
				gmac_enable_management(p_gmac, false);
				auto_negotiate_state = AUTO_NEGOTIATE_STATE_START;
			}
			return GMAC_TIMEOUT;
		}

		auto_negotiate_state = AUTO_NEGOTIATE_STATE_START;

		/* Get the auto negotiate link partner base page */
		uc_rc = gmac_phy_read(p_gmac, uc_phy_addr, GMII_ANLPAR, &ul_phy_analpar);
		if (uc_rc != GMAC_OK) {
			gmac_enable_management(p_gmac, false);
			return uc_rc;
		}


		/* Set up the GMAC link speed */
		if ((ul_phy_anar & ul_phy_analpar) & GMII_100TX_FDX) {
			/* Set MII for 100BaseTX and Full Duplex */
			uc_speed = true;
			uc_fd = true;
		} else if ((ul_phy_anar & ul_phy_analpar) & GMII_10_FDX) {
			/* Set MII for 10BaseT and Full Duplex */
			uc_speed = false;
			uc_fd = true;
		} else if ((ul_phy_anar & ul_phy_analpar) & GMII_100TX_HDX) {
			/* Set MII for 100BaseTX and half Duplex */
			uc_speed = true;
			uc_fd = false;
		} else if ((ul_phy_anar & ul_phy_analpar) & GMII_10_HDX) {
			/* Set MII for 10BaseT and half Duplex */
			uc_speed = false;
			uc_fd = false;
		}

		gmac_set_speed(p_gmac, uc_speed);
		gmac_enable_full_duplex(p_gmac, uc_fd);

		/* Select Media Independent Interface type */
		gmac_select_mii_mode(p_gmac, ETH_PHY_MODE);

		gmac_enable_transmit(GMAC, true);
		gmac_enable_receive(GMAC, true);

		gmac_enable_management(p_gmac, false);
	}
	return uc_rc;
}