|
|
@@ -36,8 +36,6 @@
|
|
|
|
|
|
#include <asm/octeon/cvmx-config.h>
|
|
|
|
|
|
-#include <asm/octeon/cvmx-mdio.h>
|
|
|
-
|
|
|
#include <asm/octeon/cvmx-helper.h>
|
|
|
#include <asm/octeon/cvmx-helper-util.h>
|
|
|
#include <asm/octeon/cvmx-helper-board.h>
|
|
|
@@ -45,17 +43,6 @@
|
|
|
#include <asm/octeon/cvmx-gmxx-defs.h>
|
|
|
#include <asm/octeon/cvmx-asxx-defs.h>
|
|
|
|
|
|
-/**
|
|
|
- * cvmx_override_board_link_get(int ipd_port) is a function
|
|
|
- * pointer. It is meant to allow customization of the process of
|
|
|
- * talking to a PHY to determine link speed. It is called every
|
|
|
- * time a PHY must be polled for link status. Users should set
|
|
|
- * this pointer to a function before calling any cvmx-helper
|
|
|
- * operations.
|
|
|
- */
|
|
|
-cvmx_helper_link_info_t(*cvmx_override_board_link_get) (int ipd_port) =
|
|
|
- NULL;
|
|
|
-
|
|
|
/**
|
|
|
* Return the MII PHY address associated with the given IPD
|
|
|
* port. A result of -1 means there isn't a MII capable PHY
|
|
|
@@ -222,12 +209,6 @@ int cvmx_helper_board_get_mii_address(int ipd_port)
|
|
|
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;
|
|
|
@@ -263,8 +244,7 @@ cvmx_helper_link_info_t __cvmx_helper_board_link_get(int ipd_port)
|
|
|
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 */
|
|
|
@@ -282,108 +262,7 @@ cvmx_helper_link_info_t __cvmx_helper_board_link_get(int ipd_port)
|
|
|
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;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- } else if (OCTEON_IS_MODEL(OCTEON_CN3XXX)
|
|
|
+ if (OCTEON_IS_MODEL(OCTEON_CN3XXX)
|
|
|
|| OCTEON_IS_MODEL(OCTEON_CN58XX)
|
|
|
|| OCTEON_IS_MODEL(OCTEON_CN50XX)) {
|
|
|
/*
|
|
|
@@ -432,176 +311,6 @@ cvmx_helper_link_info_t __cvmx_helper_board_link_get(int ipd_port)
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- * This function as a board specific method of changing the PHY
|
|
|
- * speed, duplex, and auto-negotiation. This programs the PHY and
|
|
|
- * not Octeon. This can be used to force Octeon's links to
|
|
|
- * specific settings.
|
|
|
- *
|
|
|
- * @phy_addr: The address of the PHY to program
|
|
|
- * @enable_autoneg:
|
|
|
- * Non zero if you want to enable auto-negotiation.
|
|
|
- * @link_info: Link speed to program. If the speed is zero and auto-negotiation
|
|
|
- * is enabled, all possible negotiation speeds are advertised.
|
|
|
- *
|
|
|
- * Returns Zero on success, negative on failure
|
|
|
- */
|
|
|
-int cvmx_helper_board_link_set_phy(int phy_addr,
|
|
|
- cvmx_helper_board_set_phy_link_flags_types_t
|
|
|
- link_flags,
|
|
|
- cvmx_helper_link_info_t link_info)
|
|
|
-{
|
|
|
-
|
|
|
- /* Set the flow control settings based on link_flags */
|
|
|
- if ((link_flags & set_phy_link_flags_flow_control_mask) !=
|
|
|
- set_phy_link_flags_flow_control_dont_touch) {
|
|
|
- cvmx_mdio_phy_reg_autoneg_adver_t reg_autoneg_adver;
|
|
|
- reg_autoneg_adver.u16 =
|
|
|
- cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff,
|
|
|
- CVMX_MDIO_PHY_REG_AUTONEG_ADVER);
|
|
|
- reg_autoneg_adver.s.asymmetric_pause =
|
|
|
- (link_flags & set_phy_link_flags_flow_control_mask) ==
|
|
|
- set_phy_link_flags_flow_control_enable;
|
|
|
- reg_autoneg_adver.s.pause =
|
|
|
- (link_flags & set_phy_link_flags_flow_control_mask) ==
|
|
|
- set_phy_link_flags_flow_control_enable;
|
|
|
- cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff,
|
|
|
- CVMX_MDIO_PHY_REG_AUTONEG_ADVER,
|
|
|
- reg_autoneg_adver.u16);
|
|
|
- }
|
|
|
-
|
|
|
- /* If speed isn't set and autoneg is on advertise all supported modes */
|
|
|
- if ((link_flags & set_phy_link_flags_autoneg)
|
|
|
- && (link_info.s.speed == 0)) {
|
|
|
- cvmx_mdio_phy_reg_control_t reg_control;
|
|
|
- cvmx_mdio_phy_reg_status_t reg_status;
|
|
|
- cvmx_mdio_phy_reg_autoneg_adver_t reg_autoneg_adver;
|
|
|
- cvmx_mdio_phy_reg_extended_status_t reg_extended_status;
|
|
|
- cvmx_mdio_phy_reg_control_1000_t reg_control_1000;
|
|
|
-
|
|
|
- reg_status.u16 =
|
|
|
- cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff,
|
|
|
- CVMX_MDIO_PHY_REG_STATUS);
|
|
|
- reg_autoneg_adver.u16 =
|
|
|
- cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff,
|
|
|
- CVMX_MDIO_PHY_REG_AUTONEG_ADVER);
|
|
|
- reg_autoneg_adver.s.advert_100base_t4 =
|
|
|
- reg_status.s.capable_100base_t4;
|
|
|
- reg_autoneg_adver.s.advert_10base_tx_full =
|
|
|
- reg_status.s.capable_10_full;
|
|
|
- reg_autoneg_adver.s.advert_10base_tx_half =
|
|
|
- reg_status.s.capable_10_half;
|
|
|
- reg_autoneg_adver.s.advert_100base_tx_full =
|
|
|
- reg_status.s.capable_100base_x_full;
|
|
|
- reg_autoneg_adver.s.advert_100base_tx_half =
|
|
|
- reg_status.s.capable_100base_x_half;
|
|
|
- cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff,
|
|
|
- CVMX_MDIO_PHY_REG_AUTONEG_ADVER,
|
|
|
- reg_autoneg_adver.u16);
|
|
|
- if (reg_status.s.capable_extended_status) {
|
|
|
- reg_extended_status.u16 =
|
|
|
- cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff,
|
|
|
- CVMX_MDIO_PHY_REG_EXTENDED_STATUS);
|
|
|
- reg_control_1000.u16 =
|
|
|
- cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff,
|
|
|
- CVMX_MDIO_PHY_REG_CONTROL_1000);
|
|
|
- reg_control_1000.s.advert_1000base_t_full =
|
|
|
- reg_extended_status.s.capable_1000base_t_full;
|
|
|
- reg_control_1000.s.advert_1000base_t_half =
|
|
|
- reg_extended_status.s.capable_1000base_t_half;
|
|
|
- cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff,
|
|
|
- CVMX_MDIO_PHY_REG_CONTROL_1000,
|
|
|
- reg_control_1000.u16);
|
|
|
- }
|
|
|
- reg_control.u16 =
|
|
|
- cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff,
|
|
|
- CVMX_MDIO_PHY_REG_CONTROL);
|
|
|
- reg_control.s.autoneg_enable = 1;
|
|
|
- reg_control.s.restart_autoneg = 1;
|
|
|
- cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff,
|
|
|
- CVMX_MDIO_PHY_REG_CONTROL, reg_control.u16);
|
|
|
- } else if ((link_flags & set_phy_link_flags_autoneg)) {
|
|
|
- cvmx_mdio_phy_reg_control_t reg_control;
|
|
|
- cvmx_mdio_phy_reg_status_t reg_status;
|
|
|
- cvmx_mdio_phy_reg_autoneg_adver_t reg_autoneg_adver;
|
|
|
- cvmx_mdio_phy_reg_control_1000_t reg_control_1000;
|
|
|
-
|
|
|
- reg_status.u16 =
|
|
|
- cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff,
|
|
|
- CVMX_MDIO_PHY_REG_STATUS);
|
|
|
- reg_autoneg_adver.u16 =
|
|
|
- cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff,
|
|
|
- CVMX_MDIO_PHY_REG_AUTONEG_ADVER);
|
|
|
- reg_autoneg_adver.s.advert_100base_t4 = 0;
|
|
|
- reg_autoneg_adver.s.advert_10base_tx_full = 0;
|
|
|
- reg_autoneg_adver.s.advert_10base_tx_half = 0;
|
|
|
- reg_autoneg_adver.s.advert_100base_tx_full = 0;
|
|
|
- reg_autoneg_adver.s.advert_100base_tx_half = 0;
|
|
|
- if (reg_status.s.capable_extended_status) {
|
|
|
- reg_control_1000.u16 =
|
|
|
- cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff,
|
|
|
- CVMX_MDIO_PHY_REG_CONTROL_1000);
|
|
|
- reg_control_1000.s.advert_1000base_t_full = 0;
|
|
|
- reg_control_1000.s.advert_1000base_t_half = 0;
|
|
|
- }
|
|
|
- switch (link_info.s.speed) {
|
|
|
- case 10:
|
|
|
- reg_autoneg_adver.s.advert_10base_tx_full =
|
|
|
- link_info.s.full_duplex;
|
|
|
- reg_autoneg_adver.s.advert_10base_tx_half =
|
|
|
- !link_info.s.full_duplex;
|
|
|
- break;
|
|
|
- case 100:
|
|
|
- reg_autoneg_adver.s.advert_100base_tx_full =
|
|
|
- link_info.s.full_duplex;
|
|
|
- reg_autoneg_adver.s.advert_100base_tx_half =
|
|
|
- !link_info.s.full_duplex;
|
|
|
- break;
|
|
|
- case 1000:
|
|
|
- reg_control_1000.s.advert_1000base_t_full =
|
|
|
- link_info.s.full_duplex;
|
|
|
- reg_control_1000.s.advert_1000base_t_half =
|
|
|
- !link_info.s.full_duplex;
|
|
|
- break;
|
|
|
- }
|
|
|
- cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff,
|
|
|
- CVMX_MDIO_PHY_REG_AUTONEG_ADVER,
|
|
|
- reg_autoneg_adver.u16);
|
|
|
- if (reg_status.s.capable_extended_status)
|
|
|
- cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff,
|
|
|
- CVMX_MDIO_PHY_REG_CONTROL_1000,
|
|
|
- reg_control_1000.u16);
|
|
|
- reg_control.u16 =
|
|
|
- cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff,
|
|
|
- CVMX_MDIO_PHY_REG_CONTROL);
|
|
|
- reg_control.s.autoneg_enable = 1;
|
|
|
- reg_control.s.restart_autoneg = 1;
|
|
|
- cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff,
|
|
|
- CVMX_MDIO_PHY_REG_CONTROL, reg_control.u16);
|
|
|
- } else {
|
|
|
- cvmx_mdio_phy_reg_control_t reg_control;
|
|
|
- reg_control.u16 =
|
|
|
- cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff,
|
|
|
- CVMX_MDIO_PHY_REG_CONTROL);
|
|
|
- reg_control.s.autoneg_enable = 0;
|
|
|
- reg_control.s.restart_autoneg = 1;
|
|
|
- reg_control.s.duplex = link_info.s.full_duplex;
|
|
|
- if (link_info.s.speed == 1000) {
|
|
|
- reg_control.s.speed_msb = 1;
|
|
|
- reg_control.s.speed_lsb = 0;
|
|
|
- } else if (link_info.s.speed == 100) {
|
|
|
- reg_control.s.speed_msb = 0;
|
|
|
- reg_control.s.speed_lsb = 1;
|
|
|
- } else if (link_info.s.speed == 10) {
|
|
|
- reg_control.s.speed_msb = 0;
|
|
|
- reg_control.s.speed_lsb = 0;
|
|
|
- }
|
|
|
- cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff,
|
|
|
- CVMX_MDIO_PHY_REG_CONTROL, reg_control.u16);
|
|
|
- }
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
/**
|
|
|
* This function is called by cvmx_helper_interface_probe() after it
|
|
|
* determines the number of ports Octeon can support on a specific
|
|
|
@@ -675,48 +384,6 @@ int __cvmx_helper_board_hardware_enable(int interface)
|
|
|
cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(0, interface),
|
|
|
0xc);
|
|
|
}
|
|
|
- } else if (cvmx_sysinfo_get()->board_type ==
|
|
|
- CVMX_BOARD_TYPE_CN3010_EVB_HS5) {
|
|
|
- /*
|
|
|
- * Broadcom PHYs require differnet ASX
|
|
|
- * clocks. Unfortunately many boards don't define a
|
|
|
- * new board Id and simply mangle the
|
|
|
- * CN3010_EVB_HS5
|
|
|
- */
|
|
|
- if (interface == 0) {
|
|
|
- /*
|
|
|
- * Some boards use a hacked up bootloader that
|
|
|
- * identifies them as CN3010_EVB_HS5
|
|
|
- * evaluation boards. This leads to all kinds
|
|
|
- * of configuration problems. Detect one
|
|
|
- * case, and print warning, while trying to do
|
|
|
- * the right thing.
|
|
|
- */
|
|
|
- int phy_addr = cvmx_helper_board_get_mii_address(0);
|
|
|
- if (phy_addr != -1) {
|
|
|
- int phy_identifier =
|
|
|
- cvmx_mdio_read(phy_addr >> 8,
|
|
|
- phy_addr & 0xff, 0x2);
|
|
|
- /* Is it a Broadcom PHY? */
|
|
|
- if (phy_identifier == 0x0143) {
|
|
|
- cvmx_dprintf("\n");
|
|
|
- cvmx_dprintf("ERROR:\n");
|
|
|
- cvmx_dprintf
|
|
|
- ("ERROR: Board type is CVMX_BOARD_TYPE_CN3010_EVB_HS5, but Broadcom PHY found.\n");
|
|
|
- cvmx_dprintf
|
|
|
- ("ERROR: The board type is mis-configured, and software malfunctions are likely.\n");
|
|
|
- cvmx_dprintf
|
|
|
- ("ERROR: All boards require a unique board type to identify them.\n");
|
|
|
- cvmx_dprintf("ERROR:\n");
|
|
|
- cvmx_dprintf("\n");
|
|
|
- cvmx_wait(1000000000);
|
|
|
- cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX
|
|
|
- (0, interface), 5);
|
|
|
- cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX
|
|
|
- (0, interface), 5);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
} else if (cvmx_sysinfo_get()->board_type ==
|
|
|
CVMX_BOARD_TYPE_UBNT_E100) {
|
|
|
cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(0, interface), 0);
|