📄 ucc_geth.c
字号:
volatile u32 *tx_rmon_base_ptr, u32 tx_firmware_statistics_structure_address, volatile u32 *rx_rmon_base_ptr, u32 rx_firmware_statistics_structure_address, volatile u16 *temoder_register, volatile u32 *remoder_register){ /* Note: this function does not check if */ /* the parameters it receives are NULL */ u16 temoder_value; u32 remoder_value; if (enable_tx_firmware_statistics) { out_be32(tx_rmon_base_ptr, tx_firmware_statistics_structure_address); temoder_value = in_be16(temoder_register); temoder_value |= TEMODER_TX_RMON_STATISTICS_ENABLE; out_be16(temoder_register, temoder_value); } if (enable_rx_firmware_statistics) { out_be32(rx_rmon_base_ptr, rx_firmware_statistics_structure_address); remoder_value = in_be32(remoder_register); remoder_value |= REMODER_RX_RMON_STATISTICS_ENABLE; out_be32(remoder_register, remoder_value); } return 0;}static int init_mac_station_addr_regs(u8 address_byte_0, u8 address_byte_1, u8 address_byte_2, u8 address_byte_3, u8 address_byte_4, u8 address_byte_5, volatile u32 *macstnaddr1_register, volatile u32 *macstnaddr2_register){ u32 value = 0; /* Example: for a station address of 0x12345678ABCD, */ /* 0x12 is byte 0, 0x34 is byte 1 and so on and 0xCD is byte 5 */ /* MACSTNADDR1 Register: */ /* 0 7 8 15 */ /* station address byte 5 station address byte 4 */ /* 16 23 24 31 */ /* station address byte 3 station address byte 2 */ value |= (u32) ((address_byte_2 << 0) & 0x000000FF); value |= (u32) ((address_byte_3 << 8) & 0x0000FF00); value |= (u32) ((address_byte_4 << 16) & 0x00FF0000); value |= (u32) ((address_byte_5 << 24) & 0xFF000000); out_be32(macstnaddr1_register, value); /* MACSTNADDR2 Register: */ /* 0 7 8 15 */ /* station address byte 1 station address byte 0 */ /* 16 23 24 31 */ /* reserved reserved */ value = 0; value |= (u32) ((address_byte_0 << 16) & 0x00FF0000); value |= (u32) ((address_byte_1 << 24) & 0xFF000000); out_be32(macstnaddr2_register, value); return 0;}static int init_check_frame_length_mode(int length_check, volatile u32 *maccfg2_register){ u32 value = 0; value = in_be32(maccfg2_register); if (length_check) value |= MACCFG2_LC; else value &= ~MACCFG2_LC; out_be32(maccfg2_register, value); return 0;}static int init_preamble_length(u8 preamble_length, volatile u32 *maccfg2_register){ u32 value = 0; if ((preamble_length < 3) || (preamble_length > 7)) return -EINVAL; value = in_be32(maccfg2_register); value &= ~MACCFG2_PREL_MASK; value |= (preamble_length << MACCFG2_PREL_SHIFT); out_be32(maccfg2_register, value); return 0;}static int init_rx_parameters(int reject_broadcast, int receive_short_frames, int promiscuous, volatile u32 *upsmr_register){ u32 value = 0; value = in_be32(upsmr_register); if (reject_broadcast) value |= UPSMR_BRO; else value &= ~UPSMR_BRO; if (receive_short_frames) value |= UPSMR_RSH; else value &= ~UPSMR_RSH; if (promiscuous) value |= UPSMR_PRO; else value &= ~UPSMR_PRO; out_be32(upsmr_register, value); return 0;}static int init_max_rx_buff_len(u16 max_rx_buf_len, volatile u16 *mrblr_register){ /* max_rx_buf_len value must be a multiple of 128 */ if ((max_rx_buf_len == 0) || (max_rx_buf_len % UCC_GETH_MRBLR_ALIGNMENT)) return -EINVAL; out_be16(mrblr_register, max_rx_buf_len); return 0;}static int init_min_frame_len(u16 min_frame_length, volatile u16 *minflr_register, volatile u16 *mrblr_register){ u16 mrblr_value = 0; mrblr_value = in_be16(mrblr_register); if (min_frame_length >= (mrblr_value - 4)) return -EINVAL; out_be16(minflr_register, min_frame_length); return 0;}static int adjust_enet_interface(struct ucc_geth_private *ugeth){ struct ucc_geth_info *ug_info; struct ucc_geth *ug_regs; struct ucc_fast *uf_regs; int ret_val; u32 upsmr, maccfg2, tbiBaseAddress; u16 value; ugeth_vdbg("%s: IN", __FUNCTION__); ug_info = ugeth->ug_info; ug_regs = ugeth->ug_regs; uf_regs = ugeth->uccf->uf_regs; /* Set MACCFG2 */ maccfg2 = in_be32(&ug_regs->maccfg2); maccfg2 &= ~MACCFG2_INTERFACE_MODE_MASK; if ((ugeth->max_speed == SPEED_10) || (ugeth->max_speed == SPEED_100)) maccfg2 |= MACCFG2_INTERFACE_MODE_NIBBLE; else if (ugeth->max_speed == SPEED_1000) maccfg2 |= MACCFG2_INTERFACE_MODE_BYTE; maccfg2 |= ug_info->padAndCrc; out_be32(&ug_regs->maccfg2, maccfg2); /* Set UPSMR */ upsmr = in_be32(&uf_regs->upsmr); upsmr &= ~(UPSMR_RPM | UPSMR_R10M | UPSMR_TBIM | UPSMR_RMM); if ((ugeth->phy_interface == PHY_INTERFACE_MODE_RMII) || (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII) || (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_ID) || (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_RXID) || (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_TXID) || (ugeth->phy_interface == PHY_INTERFACE_MODE_RTBI)) { upsmr |= UPSMR_RPM; switch (ugeth->max_speed) { case SPEED_10: upsmr |= UPSMR_R10M; /* FALLTHROUGH */ case SPEED_100: if (ugeth->phy_interface != PHY_INTERFACE_MODE_RTBI) upsmr |= UPSMR_RMM; } } if ((ugeth->phy_interface == PHY_INTERFACE_MODE_TBI) || (ugeth->phy_interface == PHY_INTERFACE_MODE_RTBI)) { upsmr |= UPSMR_TBIM; } out_be32(&uf_regs->upsmr, upsmr); /* Disable autonegotiation in tbi mode, because by default it comes up in autonegotiation mode. */ /* Note that this depends on proper setting in utbipar register. */ if ((ugeth->phy_interface == PHY_INTERFACE_MODE_TBI) || (ugeth->phy_interface == PHY_INTERFACE_MODE_RTBI)) { tbiBaseAddress = in_be32(&ug_regs->utbipar); tbiBaseAddress &= UTBIPAR_PHY_ADDRESS_MASK; tbiBaseAddress >>= UTBIPAR_PHY_ADDRESS_SHIFT; value = ugeth->phydev->bus->read(ugeth->phydev->bus, (u8) tbiBaseAddress, ENET_TBI_MII_CR); value &= ~0x1000; /* Turn off autonegotiation */ ugeth->phydev->bus->write(ugeth->phydev->bus, (u8) tbiBaseAddress, ENET_TBI_MII_CR, value); } init_check_frame_length_mode(ug_info->lengthCheckRx, &ug_regs->maccfg2); ret_val = init_preamble_length(ug_info->prel, &ug_regs->maccfg2); if (ret_val != 0) { if (netif_msg_probe(ugeth)) ugeth_err("%s: Preamble length must be between 3 and 7 inclusive.", __FUNCTION__); return ret_val; } return 0;}/* Called every time the controller might need to be made * aware of new link state. The PHY code conveys this * information through variables in the ugeth structure, and this * function converts those variables into the appropriate * register values, and can bring down the device if needed. */static void adjust_link(struct net_device *dev){ struct ucc_geth_private *ugeth = netdev_priv(dev); struct ucc_geth *ug_regs; struct ucc_fast *uf_regs; struct phy_device *phydev = ugeth->phydev; unsigned long flags; int new_state = 0; ug_regs = ugeth->ug_regs; uf_regs = ugeth->uccf->uf_regs; spin_lock_irqsave(&ugeth->lock, flags); if (phydev->link) { u32 tempval = in_be32(&ug_regs->maccfg2); u32 upsmr = in_be32(&uf_regs->upsmr); /* Now we make sure that we can be in full duplex mode. * If not, we operate in half-duplex mode. */ if (phydev->duplex != ugeth->oldduplex) { new_state = 1; if (!(phydev->duplex)) tempval &= ~(MACCFG2_FDX); else tempval |= MACCFG2_FDX; ugeth->oldduplex = phydev->duplex; } if (phydev->speed != ugeth->oldspeed) { new_state = 1; switch (phydev->speed) { case SPEED_1000: tempval = ((tempval & ~(MACCFG2_INTERFACE_MODE_MASK)) | MACCFG2_INTERFACE_MODE_BYTE); break; case SPEED_100: case SPEED_10: tempval = ((tempval & ~(MACCFG2_INTERFACE_MODE_MASK)) | MACCFG2_INTERFACE_MODE_NIBBLE); /* if reduced mode, re-set UPSMR.R10M */ if ((ugeth->phy_interface == PHY_INTERFACE_MODE_RMII) || (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII) || (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_ID) || (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_RXID) || (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_TXID) || (ugeth->phy_interface == PHY_INTERFACE_MODE_RTBI)) { if (phydev->speed == SPEED_10) upsmr |= UPSMR_R10M; else upsmr &= ~(UPSMR_R10M); } break; default: if (netif_msg_link(ugeth)) ugeth_warn( "%s: Ack! Speed (%d) is not 10/100/1000!", dev->name, phydev->speed); break; } ugeth->oldspeed = phydev->speed; } out_be32(&ug_regs->maccfg2, tempval); out_be32(&uf_regs->upsmr, upsmr); if (!ugeth->oldlink) { new_state = 1; ugeth->oldlink = 1; netif_schedule(dev); } } else if (ugeth->oldlink) { new_state = 1; ugeth->oldlink = 0; ugeth->oldspeed = 0; ugeth->oldduplex = -1; } if (new_state && netif_msg_link(ugeth)) phy_print_status(phydev); spin_unlock_irqrestore(&ugeth->lock, flags);}/* Configure the PHY for dev. * returns 0 if success. -1 if failure */static int init_phy(struct net_device *dev){ struct ucc_geth_private *priv = netdev_priv(dev); struct phy_device *phydev; char phy_id[BUS_ID_SIZE]; priv->oldlink = 0; priv->oldspeed = 0; priv->oldduplex = -1; snprintf(phy_id, BUS_ID_SIZE, PHY_ID_FMT, priv->ug_info->mdio_bus, priv->ug_info->phy_address); phydev = phy_connect(dev, phy_id, &adjust_link, 0, priv->phy_interface); if (IS_ERR(phydev)) { printk("%s: Could not attach to PHY\n", dev->name); return PTR_ERR(phydev); } phydev->supported &= (ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full); if (priv->max_speed == SPEED_1000) phydev->supported |= ADVERTISED_1000baseT_Full; phydev->advertising = phydev->supported; priv->phydev = phydev; return 0;}static int ugeth_graceful_stop_tx(struct ucc_geth_private *ugeth){ struct ucc_fast_private *uccf; u32 cecr_subblock; u32 temp; uccf = ugeth->uccf; /* Mask GRACEFUL STOP TX interrupt bit and clear it */ temp = in_be32(uccf->p_uccm); temp &= ~UCCE_GRA; out_be32(uccf->p_uccm, temp); out_be32(uccf->p_ucce, UCCE_GRA); /* clear by writing 1 */ /* Issue host command */ cecr_subblock = ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num); qe_issue_cmd(QE_GRACEFUL_STOP_TX, cecr_subblock, QE_CR_PROTOCOL_ETHERNET, 0); /* Wait for command to complete */ do { temp = in_be32(uccf->p_ucce); } while (!(temp & UCCE_GRA)); uccf->stopped_tx = 1; return 0;}static int ugeth_graceful_stop_rx(struct ucc_geth_private * ugeth){ struct ucc_fast_private *uccf; u32 cecr_subblock; u8 temp; uccf = ugeth->uccf; /* Clear acknowledge bit */ temp = ugeth->p_rx_glbl_pram->rxgstpack; temp &= ~GRACEFUL_STOP_ACKNOWLEDGE_RX; ugeth->p_rx_glbl_pram->rxgstpack = temp; /* Keep issuing command and checking acknowledge bit until it is asserted, according to spec */ do { /* Issue host command */ cecr_subblock = ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info. ucc_num); qe_issue_cmd(QE_GRACEFUL_STOP_RX, cecr_subblock, QE_CR_PROTOCOL_ETHERNET, 0); temp = ugeth->p_rx_glbl_pram->rxgstpack; } while (!(temp & GRACEFUL_STOP_ACKNOWLEDGE_RX));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -