⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ucc_geth.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		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 + -