/* * nae_gmac_mdio_write -Write sgmac mii PHY register. * * Input parameters: * bus - bus number, nae has two external gmac bus: 0 and 1 * phyaddr - PHY to use * regidx - register within the PHY * val - data to write to register * * Return value: * 0 - success */ int nlm_gmac_mdio_write(uint64_t nae_base, int bus, int block, int intf_type, int phyaddr, int regidx, uint16_t val) { uint32_t mdio_ld_cmd; uint32_t ctrlval; mdio_ld_cmd = nlm_read_nae_reg(nae_base, NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL + bus * 4))); if (mdio_ld_cmd & EXT_G_MDIO_CMD_LCD) { nlm_write_nae_reg(nae_base, NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL+bus*4)), (mdio_ld_cmd & ~EXT_G_MDIO_CMD_LCD)); while(nlm_read_nae_reg(nae_base, NAE_REG(block, intf_type, (EXT_G0_MDIO_RD_STAT + bus * 4))) & EXT_G_MDIO_STAT_MBSY); } /* load data into ctrl data reg */ nlm_write_nae_reg(nae_base, NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL_DATA+bus*4)), val); ctrlval = EXT_G_MDIO_CMD_SP | (phyaddr << EXT_G_MDIO_PHYADDR_POS) | (regidx << EXT_G_MDIO_REGADDR_POS); if (nlm_is_xlp8xx_ax() || nlm_is_xlp8xx_b0() || nlm_is_xlp3xx_ax()) ctrlval |= EXT_G_MDIO_DIV; else ctrlval |= EXT_G_MDIO_DIV_WITH_HW_DIV64; nlm_write_nae_reg(nae_base, NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL+bus*4)), ctrlval); nlm_write_nae_reg(nae_base, NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL+bus*4)), ctrlval | EXT_G_MDIO_CMD_LCD); DELAY(1000); /* poll master busy bit until it is not busy */ while(nlm_read_nae_reg(nae_base, NAE_REG(block, intf_type, (EXT_G0_MDIO_RD_STAT + bus * 4))) & EXT_G_MDIO_STAT_MBSY); nlm_write_nae_reg(nae_base, NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL+bus*4)), ctrlval); return (0); }
/* Internal MDIO WRITE Routines */ int nlm_int_gmac_mdio_write(uint64_t nae_base, int bus, int block, int intf_type, int phyaddr, int regidx, uint16_t val) { uint32_t mdio_ld_cmd; uint32_t ctrlval; ctrlval = INT_MDIO_CTRL_SMP | (phyaddr << INT_MDIO_CTRL_PHYADDR_POS) | (regidx << INT_MDIO_CTRL_DEVTYPE_POS) | (1 << INT_MDIO_CTRL_OP_POS) | (1 << INT_MDIO_CTRL_ST_POS) | (7 << INT_MDIO_CTRL_XDIV_POS) | (2 << INT_MDIO_CTRL_TA_POS) | (1 << INT_MDIO_CTRL_MIIM_POS) | (1 << INT_MDIO_CTRL_MCDIV_POS); mdio_ld_cmd = nlm_read_nae_reg(nae_base, NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus * 4))); if (mdio_ld_cmd & INT_MDIO_CTRL_CMD_LOAD) { nlm_write_nae_reg(nae_base, NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus*4)), (mdio_ld_cmd & ~INT_MDIO_CTRL_CMD_LOAD)); } /* load data into ctrl data reg */ nlm_write_nae_reg(nae_base, NAE_REG(block, intf_type, (INT_MDIO_CTRL_DATA + bus * 4)), val); nlm_write_nae_reg(nae_base, NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus * 4)), ctrlval); nlm_write_nae_reg(nae_base, NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus * 4)), ctrlval | (1 << INT_MDIO_CTRL_LOAD_POS)); /* poll master busy bit until it is not busy */ while(nlm_read_nae_reg(nae_base, NAE_REG(block, intf_type, (INT_MDIO_RD_STAT + bus * 4))) & INT_MDIO_STAT_MBSY) { } nlm_write_nae_reg(nae_base, NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus * 4)), ctrlval); return (0); }
/* Internal MDIO READ/WRITE Routines */ int nlm_int_gmac_mdio_read(uint64_t nae_base, int bus, int block, int intf_type, int phyaddr, int regidx) { uint32_t mdio_ld_cmd; uint32_t ctrlval; ctrlval = INT_MDIO_CTRL_SMP | (phyaddr << INT_MDIO_CTRL_PHYADDR_POS) | (regidx << INT_MDIO_CTRL_DEVTYPE_POS) | (2 << INT_MDIO_CTRL_OP_POS) | (1 << INT_MDIO_CTRL_ST_POS) | (7 << INT_MDIO_CTRL_XDIV_POS) | (2 << INT_MDIO_CTRL_TA_POS) | (2 << INT_MDIO_CTRL_MIIM_POS) | (1 << INT_MDIO_CTRL_MCDIV_POS); mdio_ld_cmd = nlm_read_nae_reg(nae_base, NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus * 4))); if (mdio_ld_cmd & INT_MDIO_CTRL_CMD_LOAD) { nlm_write_nae_reg(nae_base, NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus*4)), (mdio_ld_cmd & ~INT_MDIO_CTRL_CMD_LOAD)); } nlm_write_nae_reg(nae_base, NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus * 4)), ctrlval); /* Toggle Load Cmd Bit */ nlm_write_nae_reg(nae_base, NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus * 4)), ctrlval | (1 << INT_MDIO_CTRL_LOAD_POS)); /* poll master busy bit until it is not busy */ while(nlm_read_nae_reg(nae_base, NAE_REG(block, intf_type, (INT_MDIO_RD_STAT + bus * 4))) & INT_MDIO_STAT_MBSY) { } nlm_write_nae_reg(nae_base, NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus * 4)), ctrlval); /* Read the data back */ return nlm_read_nae_reg(nae_base, NAE_REG(block, intf_type, (INT_MDIO_RD_STAT + bus * 4))); }
void nlm_xaui_pcs_init(uint64_t nae_base, int xaui_cplx_mask) { int block, lane_ctrl, reg; int cplx_lane_enable; int lane_enable = 0; uint32_t regval; cplx_lane_enable = LM_XAUI | (LM_XAUI << 4) | (LM_XAUI << 8) | (LM_XAUI << 12); if (xaui_cplx_mask == 0) return; /* write 0x2 to enable SGMII for all lane */ block = 7; if (xaui_cplx_mask & 0x3) { /* Complexes 0, 1 */ lane_enable = nlm_read_nae_reg(nae_base, NAE_REG(block, LANE_CFG, LANE_CFG_CPLX_0_1)); if (xaui_cplx_mask & 0x1) { /* Complex 0 */ lane_enable &= ~(0xFFFF); lane_enable |= cplx_lane_enable; } if (xaui_cplx_mask & 0x2) { /* Complex 1 */ lane_enable &= ~(0xFFFF<<16); lane_enable |= (cplx_lane_enable << 16); } nlm_write_nae_reg(nae_base, NAE_REG(block, LANE_CFG, LANE_CFG_CPLX_0_1), lane_enable); } lane_enable = 0; if (xaui_cplx_mask & 0xc) { /* Complexes 2, 3 */ lane_enable = nlm_read_nae_reg(nae_base, NAE_REG(block, LANE_CFG, LANE_CFG_CPLX_2_3)); if (xaui_cplx_mask & 0x4) { /* Complex 2 */ lane_enable &= ~(0xFFFF); lane_enable |= cplx_lane_enable; } if (xaui_cplx_mask & 0x8) { /* Complex 3 */ lane_enable &= ~(0xFFFF<<16); lane_enable |= (cplx_lane_enable << 16); } nlm_write_nae_reg(nae_base, NAE_REG(block, LANE_CFG, LANE_CFG_CPLX_2_3), lane_enable); } /* Bring txpll out of reset */ for (block = 0; block < 4; block++) { if ((xaui_cplx_mask & (1 << block)) == 0) continue; for (lane_ctrl = PHY_LANE_0_CTRL; lane_ctrl <= PHY_LANE_3_CTRL; lane_ctrl++) { if (!nlm_is_xlp8xx_ax()) xlp_nae_lane_reset_txpll(nae_base, block, lane_ctrl, PHYMODE_XAUI); else xlp_ax_nae_lane_reset_txpll(nae_base, block, lane_ctrl, PHYMODE_XAUI); } } /* Wait for Rx & TX clock stable */ for (block = 0; block < 4; block++) { if ((xaui_cplx_mask & (1 << block)) == 0) continue; for (lane_ctrl = PHY_LANE_0_CTRL; lane_ctrl <= PHY_LANE_3_CTRL; lane_ctrl++) { reg = NAE_REG(block, PHY, lane_ctrl - 4); /* Wait for TX clock to be set */ do { regval = nlm_read_nae_reg(nae_base, reg); } while ((regval & LANE_TX_CLK) == 0); /* Wait for RX clock to be set */ do { regval = nlm_read_nae_reg(nae_base, reg); } while ((regval & LANE_RX_CLK) == 0); /* Wait for XAUI Lane fault to be cleared */ do { regval = nlm_read_nae_reg(nae_base, reg); } while ((regval & XAUI_LANE_FAULT) != 0); } } }