示例#1
0
void cvm_oct_rgmii_uninit(struct ifnet *ifp)
{
	cvm_oct_private_t *priv = (cvm_oct_private_t *)ifp->if_softc;
	cvm_oct_common_uninit(ifp);

	/* Only true RGMII ports need to be polled. In GMII mode, port 0 is really
	   a RGMII port */
	if (((priv->imode == CVMX_HELPER_INTERFACE_MODE_GMII) && (priv->port == 0)) ||
	    (priv->imode == CVMX_HELPER_INTERFACE_MODE_RGMII)) {

		if (cvmx_sysinfo_get()->board_type != CVMX_BOARD_TYPE_SIM) {

			cvmx_gmxx_rxx_int_en_t gmx_rx_int_en;
			int interface = INTERFACE(priv->port);
			int index = INDEX(priv->port);

			/* Disable interrupts on inband status changes for this port */
			gmx_rx_int_en.u64 = cvmx_read_csr(CVMX_GMXX_RXX_INT_EN(index, interface));
			gmx_rx_int_en.s.phy_dupx = 0;
			gmx_rx_int_en.s.phy_link = 0;
			gmx_rx_int_en.s.phy_spd = 0;
			cvmx_write_csr(CVMX_GMXX_RXX_INT_EN(index, interface), gmx_rx_int_en.u64);
		}
	}

	/* Remove the interrupt handler when the last port is removed */
	number_rgmii_ports--;
	if (number_rgmii_ports == 0)
		panic("%s: need to implement IRQ release.", __func__);
}
示例#2
0
void cvm_oct_rgmii_uninit(struct net_device *dev)
{
	struct octeon_ethernet *priv = netdev_priv(dev);
	cvm_oct_common_uninit(dev);

	
	if (((priv->imode == CVMX_HELPER_INTERFACE_MODE_GMII)
	     && (priv->port == 0))
	    || (priv->imode == CVMX_HELPER_INTERFACE_MODE_RGMII)) {

		if (!octeon_is_simulation()) {

			union cvmx_gmxx_rxx_int_en gmx_rx_int_en;
			int interface = INTERFACE(priv->port);
			int index = INDEX(priv->port);

			
			gmx_rx_int_en.u64 =
			    cvmx_read_csr(CVMX_GMXX_RXX_INT_EN
					  (index, interface));
			gmx_rx_int_en.s.phy_dupx = 0;
			gmx_rx_int_en.s.phy_link = 0;
			gmx_rx_int_en.s.phy_spd = 0;
			cvmx_write_csr(CVMX_GMXX_RXX_INT_EN(index, interface),
				       gmx_rx_int_en.u64);
		}
	}

	
	number_rgmii_ports--;
	if (number_rgmii_ports == 0)
		free_irq(OCTEON_IRQ_RML, &number_rgmii_ports);
}
示例#3
0
int cvm_oct_rgmii_init(struct net_device *dev)
{
	struct octeon_ethernet *priv = netdev_priv(dev);
	int r;

	cvm_oct_common_init(dev);
	dev->netdev_ops->ndo_stop(dev);
	INIT_WORK(&priv->port_work, cvm_oct_rgmii_immediate_poll);
	/*
	 * Due to GMX errata in CN3XXX series chips, it is necessary
	 * to take the link down immediately when the PHY changes
	 * state. In order to do this we call the poll function every
	 * time the RGMII inband status changes.  This may cause
	 * problems if the PHY doesn't implement inband status
	 * properly.
	 */
	if (number_rgmii_ports == 0) {
		r = request_irq(OCTEON_IRQ_RML, cvm_oct_rgmii_rml_interrupt,
				IRQF_SHARED, "RGMII", &number_rgmii_ports);
		if (r != 0)
			return r;
	}
	number_rgmii_ports++;

	/*
	 * Only true RGMII ports need to be polled. In GMII mode, port
	 * 0 is really a RGMII port.
	 */
	if (((priv->imode == CVMX_HELPER_INTERFACE_MODE_GMII)
	     && (priv->port == 0))
	    || (priv->imode == CVMX_HELPER_INTERFACE_MODE_RGMII)) {

		if (!octeon_is_simulation()) {

			union cvmx_gmxx_rxx_int_en gmx_rx_int_en;
			int interface = INTERFACE(priv->port);
			int index = INDEX(priv->port);

			/*
			 * Enable interrupts on inband status changes
			 * for this port.
			 */
			gmx_rx_int_en.u64 =
			    cvmx_read_csr(CVMX_GMXX_RXX_INT_EN
					  (index, interface));
			gmx_rx_int_en.s.phy_dupx = 1;
			gmx_rx_int_en.s.phy_link = 1;
			gmx_rx_int_en.s.phy_spd = 1;
			cvmx_write_csr(CVMX_GMXX_RXX_INT_EN(index, interface),
				       gmx_rx_int_en.u64);
			priv->poll = cvm_oct_rgmii_poll;
		}
	}

	return 0;
}
示例#4
0
int cvm_oct_sgmii_stop(struct net_device *dev)
{
	union cvmx_gmxx_prtx_cfg gmx_cfg;
	struct octeon_ethernet *priv = netdev_priv(dev);

	gmx_cfg.u64 = cvmx_read_csr(priv->gmx_base + GMX_PRT_CFG);
	gmx_cfg.s.en = 0;
	cvmx_write_csr(priv->gmx_base + GMX_PRT_CFG, gmx_cfg.u64);

	if (priv->hw_status_notifier.notifier_call) {
		struct octeon_hw_status_reg sr;
		memset(&sr, 0, sizeof(sr));

		sr.reg = CVMX_GMXX_RXX_INT_REG(priv->interface_port,
					       priv->interface);
		sr.mask_reg = CVMX_GMXX_RXX_INT_EN(priv->interface_port,
						   priv->interface);
		sr.ack_w1c = 1;
		sr.bit = INT_BIT_LOC_FAULT;
		octeon_hw_status_remove_source(&sr);
		sr.bit = INT_BIT_REM_FAULT;
		octeon_hw_status_remove_source(&sr);
		octeon_hw_status_notifier_unregister(&priv->hw_status_notifier);
		priv->hw_status_notifier.notifier_call = NULL;
	}

	return cvm_oct_common_stop(dev);
}
示例#5
0
int cvm_oct_rgmii_init(struct net_device *dev)
{
	struct octeon_ethernet *priv = netdev_priv(dev);
	int r;

	cvm_oct_common_init(dev);
	dev->netdev_ops->ndo_stop(dev);

	
	if (number_rgmii_ports == 0) {
		r = request_irq(OCTEON_IRQ_RML, cvm_oct_rgmii_rml_interrupt,
				IRQF_SHARED, "RGMII", &number_rgmii_ports);
	}
	number_rgmii_ports++;

	
	if (((priv->imode == CVMX_HELPER_INTERFACE_MODE_GMII)
	     && (priv->port == 0))
	    || (priv->imode == CVMX_HELPER_INTERFACE_MODE_RGMII)) {

		if (!octeon_is_simulation()) {

			union cvmx_gmxx_rxx_int_en gmx_rx_int_en;
			int interface = INTERFACE(priv->port);
			int index = INDEX(priv->port);

			
			gmx_rx_int_en.u64 =
			    cvmx_read_csr(CVMX_GMXX_RXX_INT_EN
					  (index, interface));
			gmx_rx_int_en.s.phy_dupx = 1;
			gmx_rx_int_en.s.phy_link = 1;
			gmx_rx_int_en.s.phy_spd = 1;
			cvmx_write_csr(CVMX_GMXX_RXX_INT_EN(index, interface),
				       gmx_rx_int_en.u64);
			priv->poll = cvm_oct_rgmii_poll;
		}
	}

	return 0;
}
示例#6
0
void cvm_oct_rgmii_uninit(struct net_device *dev)
{
	struct octeon_ethernet *priv = netdev_priv(dev);
	cvm_oct_common_uninit(dev);

	/*
	 * Only true RGMII ports need to be polled. In GMII mode, port
	 * 0 is really a RGMII port.
	 */
	if (((priv->imode == CVMX_HELPER_INTERFACE_MODE_GMII)
	     && (priv->port == 0))
	    || (priv->imode == CVMX_HELPER_INTERFACE_MODE_RGMII)) {

		if (!octeon_is_simulation()) {

			union cvmx_gmxx_rxx_int_en gmx_rx_int_en;
			int interface = INTERFACE(priv->port);
			int index = INDEX(priv->port);

			/*
			 * Disable interrupts on inband status changes
			 * for this port.
			 */
			gmx_rx_int_en.u64 =
			    cvmx_read_csr(CVMX_GMXX_RXX_INT_EN
					  (index, interface));
			gmx_rx_int_en.s.phy_dupx = 0;
			gmx_rx_int_en.s.phy_link = 0;
			gmx_rx_int_en.s.phy_spd = 0;
			cvmx_write_csr(CVMX_GMXX_RXX_INT_EN(index, interface),
				       gmx_rx_int_en.u64);
		}
	}

	/* Remove the interrupt handler when the last port is removed. */
	number_rgmii_ports--;
	if (number_rgmii_ports == 0)
		free_irq(OCTEON_IRQ_RML, &number_rgmii_ports);
	cancel_work_sync(&priv->port_work);
}
示例#7
0
static irqreturn_t cvm_oct_rgmii_rml_interrupt(int cpl, void *dev_id)
{
	union cvmx_npi_rsl_int_blocks rsl_int_blocks;
	int index;
	irqreturn_t return_status = IRQ_NONE;

	rsl_int_blocks.u64 = cvmx_read_csr(CVMX_NPI_RSL_INT_BLOCKS);

	/* Check and see if this interrupt was caused by the GMX0 block */
	if (rsl_int_blocks.s.gmx0) {

		int interface = 0;
		/* Loop through every port of this interface */
		for (index = 0;
		     index < cvmx_helper_ports_on_interface(interface);
		     index++) {

			/* Read the GMX interrupt status bits */
			union cvmx_gmxx_rxx_int_reg gmx_rx_int_reg;
			gmx_rx_int_reg.u64 = cvmx_read_csr(CVMX_GMXX_RXX_INT_REG(index, interface));
			gmx_rx_int_reg.u64 &= cvmx_read_csr(CVMX_GMXX_RXX_INT_EN(index, interface));
			/* Poll the port if inband status changed */
			if (gmx_rx_int_reg.s.phy_dupx
			    || gmx_rx_int_reg.s.phy_link
			    || gmx_rx_int_reg.s.phy_spd) {
				struct octeon_ethernet *priv = cvm_oct_by_port[cvmx_helper_get_ipd_port(interface, index)];

				if (priv && !atomic_read(&cvm_oct_poll_queue_stopping))
					queue_work(cvm_oct_poll_queue, &priv->port_work);

				gmx_rx_int_reg.u64 = 0;
				gmx_rx_int_reg.s.phy_dupx = 1;
				gmx_rx_int_reg.s.phy_link = 1;
				gmx_rx_int_reg.s.phy_spd = 1;
				cvmx_write_csr(CVMX_GMXX_RXX_INT_REG(index, interface), gmx_rx_int_reg.u64);
				return_status = IRQ_HANDLED;
			}
		}
	}

	/* Check and see if this interrupt was caused by the GMX1 block */
	if (rsl_int_blocks.s.gmx1) {

		int interface = 1;
		/* Loop through every port of this interface */
		for (index = 0;
		     index < cvmx_helper_ports_on_interface(interface);
		     index++) {

			/* Read the GMX interrupt status bits */
			union cvmx_gmxx_rxx_int_reg gmx_rx_int_reg;
			gmx_rx_int_reg.u64 = cvmx_read_csr(CVMX_GMXX_RXX_INT_REG(index, interface));
			gmx_rx_int_reg.u64 &= cvmx_read_csr(CVMX_GMXX_RXX_INT_EN(index, interface));
			/* Poll the port if inband status changed */
			if (gmx_rx_int_reg.s.phy_dupx
			    || gmx_rx_int_reg.s.phy_link
			    || gmx_rx_int_reg.s.phy_spd) {
				struct octeon_ethernet *priv = cvm_oct_by_port[cvmx_helper_get_ipd_port(interface, index)];

				if (priv && !atomic_read(&cvm_oct_poll_queue_stopping))
					queue_work(cvm_oct_poll_queue, &priv->port_work);

				gmx_rx_int_reg.u64 = 0;
				gmx_rx_int_reg.s.phy_dupx = 1;
				gmx_rx_int_reg.s.phy_link = 1;
				gmx_rx_int_reg.s.phy_spd = 1;
				cvmx_write_csr(CVMX_GMXX_RXX_INT_REG(index, interface), gmx_rx_int_reg.u64);
				return_status = IRQ_HANDLED;
			}
		}
	}
	return return_status;
}
示例#8
0
int cvm_oct_sgmii_open(struct net_device *dev)
{
	struct octeon_hw_status_reg sr[3];
	union cvmx_gmxx_prtx_cfg gmx_cfg;
	struct octeon_ethernet *priv = netdev_priv(dev);
	cvmx_helper_link_info_t link_info;
	cvmx_helper_interface_mode_t imode;
	int rv, i;
	u64 en_mask;

	rv = cvm_oct_phy_setup_device(dev);
	if (rv)
		return rv;

	gmx_cfg.u64 = cvmx_read_csr(priv->gmx_base + GMX_PRT_CFG);
	gmx_cfg.s.en = 1;
	cvmx_write_csr(priv->gmx_base + GMX_PRT_CFG, gmx_cfg.u64);

	if (octeon_is_simulation())
		return 0;

	if (priv->phydev) {
		int r = phy_read_status(priv->phydev);
		if (r == 0 && priv->phydev->link == 0)
			netif_carrier_off(dev);
		cvm_oct_adjust_link(dev);
	} else {
		link_info = cvmx_helper_link_get(priv->ipd_port);
		if (!link_info.s.link_up)
			netif_carrier_off(dev);
		priv->poll = cvm_oct_sgmii_poll;
		cvm_oct_sgmii_poll(dev);
	}
	imode = cvmx_helper_interface_get_mode(priv->interface);
	switch (imode) {
	case CVMX_HELPER_INTERFACE_MODE_XAUI:
	case CVMX_HELPER_INTERFACE_MODE_RXAUI:
		/* Handle GMXX_RXX_INT_REG[LOC_FAULT,REM_FAULT]*/
		priv->hw_status_notifier.priority = 10;
		priv->hw_status_notifier.notifier_call = cvm_oct_sgmii_hw_status;
		octeon_hw_status_notifier_register(&priv->hw_status_notifier);
		memset(sr, 0, sizeof(sr));
		i = 0;
		en_mask = 0;
		if (OCTEON_IS_OCTEONPLUS()) {
			sr[i].reg = 46; /* RML */
			sr[i].reg_is_hwint = 1;
			sr[i].has_child = 1;
			i++;
			sr[i].reg = CVMX_NPEI_RSL_INT_BLOCKS;
			/* GMX[priv->interface]*/
			sr[i].bit = priv->interface + 1;
			sr[i].has_child = 1;
			i++;
		} else if (octeon_has_feature(OCTEON_FEATURE_CIU2)) {
			/* PKT[AGX[priv->interface]]*/
			sr[i].reg = (6 << 6) | priv->interface;
			sr[i].reg_is_hwint = 1;
			sr[i].has_child = 1;
			i++;
		} else {
			/* INT_SUM1[AGX[priv->interface]]*/
			sr[i].reg = (1 << 6) | (priv->interface + 36);
			sr[i].reg_is_hwint = 1;
			sr[i].has_child = 1;
			i++;
		}
		sr[i].reg = CVMX_GMXX_RXX_INT_REG(priv->interface_port,
						  priv->interface);
		sr[i].mask_reg = CVMX_GMXX_RXX_INT_EN(priv->interface_port,
						      priv->interface);
		sr[i].ack_w1c = 1;

		sr[i].bit = INT_BIT_LOC_FAULT;
		en_mask |= 1ull << sr[i].bit;
		octeon_hw_status_add_source(sr);

		sr[i].bit = INT_BIT_REM_FAULT;
		en_mask |= 1ull << sr[i].bit;
		octeon_hw_status_add_source(sr);

		octeon_hw_status_enable(sr[i].reg, en_mask);
		break;
	default:
		break;
	}
	return 0;
}
/**
 * __cvmx_interrupt_gmxx_rxx_int_en_enable enables all interrupt bits in cvmx_gmxx_rxx_int_en_t
 */
void __cvmx_interrupt_gmxx_rxx_int_en_enable(int index, int block)
{
	union cvmx_gmxx_rxx_int_en gmx_rx_int_en;
	cvmx_write_csr(CVMX_GMXX_RXX_INT_REG(index, block),
		       cvmx_read_csr(CVMX_GMXX_RXX_INT_REG(index, block)));
	gmx_rx_int_en.u64 = 0;
	if (OCTEON_IS_MODEL(OCTEON_CN56XX)) {
		/* Skipping gmx_rx_int_en.s.reserved_29_63 */
		gmx_rx_int_en.s.hg2cc = 1;
		gmx_rx_int_en.s.hg2fld = 1;
		gmx_rx_int_en.s.undat = 1;
		gmx_rx_int_en.s.uneop = 1;
		gmx_rx_int_en.s.unsop = 1;
		gmx_rx_int_en.s.bad_term = 1;
		gmx_rx_int_en.s.bad_seq = 1;
		gmx_rx_int_en.s.rem_fault = 1;
		gmx_rx_int_en.s.loc_fault = 1;
		gmx_rx_int_en.s.pause_drp = 1;
		/* Skipping gmx_rx_int_en.s.reserved_16_18 */
		/*gmx_rx_int_en.s.ifgerr = 1; */
		/*gmx_rx_int_en.s.coldet = 1; // Collsion detect */
		/*gmx_rx_int_en.s.falerr = 1; // False carrier error or extend error after slottime */
		/*gmx_rx_int_en.s.rsverr = 1; // RGMII reserved opcodes */
		/*gmx_rx_int_en.s.pcterr = 1; // Bad Preamble / Protocol */
		gmx_rx_int_en.s.ovrerr = 1;
		/* Skipping gmx_rx_int_en.s.reserved_9_9 */
		gmx_rx_int_en.s.skperr = 1;
		gmx_rx_int_en.s.rcverr = 1;
		/* Skipping gmx_rx_int_en.s.reserved_5_6 */
		/*gmx_rx_int_en.s.fcserr = 1; // FCS errors are handled when we get work */
		gmx_rx_int_en.s.jabber = 1;
		/* Skipping gmx_rx_int_en.s.reserved_2_2 */
		gmx_rx_int_en.s.carext = 1;
		/* Skipping gmx_rx_int_en.s.reserved_0_0 */
	}
	if (OCTEON_IS_MODEL(OCTEON_CN30XX)) {
		/* Skipping gmx_rx_int_en.s.reserved_19_63 */
		/*gmx_rx_int_en.s.phy_dupx = 1; */
		/*gmx_rx_int_en.s.phy_spd = 1; */
		/*gmx_rx_int_en.s.phy_link = 1; */
		/*gmx_rx_int_en.s.ifgerr = 1; */
		/*gmx_rx_int_en.s.coldet = 1; // Collsion detect */
		/*gmx_rx_int_en.s.falerr = 1; // False carrier error or extend error after slottime */
		/*gmx_rx_int_en.s.rsverr = 1; // RGMII reserved opcodes */
		/*gmx_rx_int_en.s.pcterr = 1; // Bad Preamble / Protocol */
		gmx_rx_int_en.s.ovrerr = 1;
		gmx_rx_int_en.s.niberr = 1;
		gmx_rx_int_en.s.skperr = 1;
		gmx_rx_int_en.s.rcverr = 1;
		/*gmx_rx_int_en.s.lenerr = 1; // Length errors are handled when we get work */
		gmx_rx_int_en.s.alnerr = 1;
		/*gmx_rx_int_en.s.fcserr = 1; // FCS errors are handled when we get work */
		gmx_rx_int_en.s.jabber = 1;
		gmx_rx_int_en.s.maxerr = 1;
		gmx_rx_int_en.s.carext = 1;
		gmx_rx_int_en.s.minerr = 1;
	}
	if (OCTEON_IS_MODEL(OCTEON_CN50XX)) {
		/* Skipping gmx_rx_int_en.s.reserved_20_63 */
		gmx_rx_int_en.s.pause_drp = 1;
		/*gmx_rx_int_en.s.phy_dupx = 1; */
		/*gmx_rx_int_en.s.phy_spd = 1; */
		/*gmx_rx_int_en.s.phy_link = 1; */
		/*gmx_rx_int_en.s.ifgerr = 1; */
		/*gmx_rx_int_en.s.coldet = 1; // Collsion detect */
		/*gmx_rx_int_en.s.falerr = 1; // False carrier error or extend error after slottime */
		/*gmx_rx_int_en.s.rsverr = 1; // RGMII reserved opcodes */
		/*gmx_rx_int_en.s.pcterr = 1; // Bad Preamble / Protocol */
		gmx_rx_int_en.s.ovrerr = 1;
		gmx_rx_int_en.s.niberr = 1;
		gmx_rx_int_en.s.skperr = 1;
		gmx_rx_int_en.s.rcverr = 1;
		/* Skipping gmx_rx_int_en.s.reserved_6_6 */
		gmx_rx_int_en.s.alnerr = 1;
		/*gmx_rx_int_en.s.fcserr = 1; // FCS errors are handled when we get work */
		gmx_rx_int_en.s.jabber = 1;
		/* Skipping gmx_rx_int_en.s.reserved_2_2 */
		gmx_rx_int_en.s.carext = 1;
		/* Skipping gmx_rx_int_en.s.reserved_0_0 */
	}
	if (OCTEON_IS_MODEL(OCTEON_CN38XX)) {
		/* Skipping gmx_rx_int_en.s.reserved_19_63 */
		/*gmx_rx_int_en.s.phy_dupx = 1; */
		/*gmx_rx_int_en.s.phy_spd = 1; */
		/*gmx_rx_int_en.s.phy_link = 1; */
		/*gmx_rx_int_en.s.ifgerr = 1; */
		/*gmx_rx_int_en.s.coldet = 1; // Collsion detect */
		/*gmx_rx_int_en.s.falerr = 1; // False carrier error or extend error after slottime */
		/*gmx_rx_int_en.s.rsverr = 1; // RGMII reserved opcodes */
		/*gmx_rx_int_en.s.pcterr = 1; // Bad Preamble / Protocol */
		gmx_rx_int_en.s.ovrerr = 1;
		gmx_rx_int_en.s.niberr = 1;
		gmx_rx_int_en.s.skperr = 1;
		gmx_rx_int_en.s.rcverr = 1;
		/*gmx_rx_int_en.s.lenerr = 1; // Length errors are handled when we get work */
		gmx_rx_int_en.s.alnerr = 1;
		/*gmx_rx_int_en.s.fcserr = 1; // FCS errors are handled when we get work */
		gmx_rx_int_en.s.jabber = 1;
		gmx_rx_int_en.s.maxerr = 1;
		gmx_rx_int_en.s.carext = 1;
		gmx_rx_int_en.s.minerr = 1;
	}
	if (OCTEON_IS_MODEL(OCTEON_CN31XX)) {
		/* Skipping gmx_rx_int_en.s.reserved_19_63 */
		/*gmx_rx_int_en.s.phy_dupx = 1; */
		/*gmx_rx_int_en.s.phy_spd = 1; */
		/*gmx_rx_int_en.s.phy_link = 1; */
		/*gmx_rx_int_en.s.ifgerr = 1; */
		/*gmx_rx_int_en.s.coldet = 1; // Collsion detect */
		/*gmx_rx_int_en.s.falerr = 1; // False carrier error or extend error after slottime */
		/*gmx_rx_int_en.s.rsverr = 1; // RGMII reserved opcodes */
		/*gmx_rx_int_en.s.pcterr = 1; // Bad Preamble / Protocol */
		gmx_rx_int_en.s.ovrerr = 1;
		gmx_rx_int_en.s.niberr = 1;
		gmx_rx_int_en.s.skperr = 1;
		gmx_rx_int_en.s.rcverr = 1;
		/*gmx_rx_int_en.s.lenerr = 1; // Length errors are handled when we get work */
		gmx_rx_int_en.s.alnerr = 1;
		/*gmx_rx_int_en.s.fcserr = 1; // FCS errors are handled when we get work */
		gmx_rx_int_en.s.jabber = 1;
		gmx_rx_int_en.s.maxerr = 1;
		gmx_rx_int_en.s.carext = 1;
		gmx_rx_int_en.s.minerr = 1;
	}
	if (OCTEON_IS_MODEL(OCTEON_CN58XX)) {
		/* Skipping gmx_rx_int_en.s.reserved_20_63 */
		gmx_rx_int_en.s.pause_drp = 1;
		/*gmx_rx_int_en.s.phy_dupx = 1; */
		/*gmx_rx_int_en.s.phy_spd = 1; */
		/*gmx_rx_int_en.s.phy_link = 1; */
		/*gmx_rx_int_en.s.ifgerr = 1; */
		/*gmx_rx_int_en.s.coldet = 1; // Collsion detect */
		/*gmx_rx_int_en.s.falerr = 1; // False carrier error or extend error after slottime */
		/*gmx_rx_int_en.s.rsverr = 1; // RGMII reserved opcodes */
		/*gmx_rx_int_en.s.pcterr = 1; // Bad Preamble / Protocol */
		gmx_rx_int_en.s.ovrerr = 1;
		gmx_rx_int_en.s.niberr = 1;
		gmx_rx_int_en.s.skperr = 1;
		gmx_rx_int_en.s.rcverr = 1;
		/*gmx_rx_int_en.s.lenerr = 1; // Length errors are handled when we get work */
		gmx_rx_int_en.s.alnerr = 1;
		/*gmx_rx_int_en.s.fcserr = 1; // FCS errors are handled when we get work */
		gmx_rx_int_en.s.jabber = 1;
		gmx_rx_int_en.s.maxerr = 1;
		gmx_rx_int_en.s.carext = 1;
		gmx_rx_int_en.s.minerr = 1;
	}
	if (OCTEON_IS_MODEL(OCTEON_CN52XX)) {
		/* Skipping gmx_rx_int_en.s.reserved_29_63 */
		gmx_rx_int_en.s.hg2cc = 1;
		gmx_rx_int_en.s.hg2fld = 1;
		gmx_rx_int_en.s.undat = 1;
		gmx_rx_int_en.s.uneop = 1;
		gmx_rx_int_en.s.unsop = 1;
		gmx_rx_int_en.s.bad_term = 1;
		gmx_rx_int_en.s.bad_seq = 0;
		gmx_rx_int_en.s.rem_fault = 1;
		gmx_rx_int_en.s.loc_fault = 0;
		gmx_rx_int_en.s.pause_drp = 1;
		/* Skipping gmx_rx_int_en.s.reserved_16_18 */
		/*gmx_rx_int_en.s.ifgerr = 1; */
		/*gmx_rx_int_en.s.coldet = 1; // Collsion detect */
		/*gmx_rx_int_en.s.falerr = 1; // False carrier error or extend error after slottime */
		/*gmx_rx_int_en.s.rsverr = 1; // RGMII reserved opcodes */
		/*gmx_rx_int_en.s.pcterr = 1; // Bad Preamble / Protocol */
		gmx_rx_int_en.s.ovrerr = 1;
		/* Skipping gmx_rx_int_en.s.reserved_9_9 */
		gmx_rx_int_en.s.skperr = 1;
		gmx_rx_int_en.s.rcverr = 1;
		/* Skipping gmx_rx_int_en.s.reserved_5_6 */
		/*gmx_rx_int_en.s.fcserr = 1; // FCS errors are handled when we get work */
		gmx_rx_int_en.s.jabber = 1;
		/* Skipping gmx_rx_int_en.s.reserved_2_2 */
		gmx_rx_int_en.s.carext = 1;
		/* Skipping gmx_rx_int_en.s.reserved_0_0 */
	}
	cvmx_write_csr(CVMX_GMXX_RXX_INT_EN(index, block), gmx_rx_int_en.u64);
}
示例#10
0
int cvm_oct_rgmii_init(struct ifnet *ifp)
{
	struct octebus_softc *sc;
	cvm_oct_private_t *priv = (cvm_oct_private_t *)ifp->if_softc;
	int error;
	int rid;

	if (cvm_oct_common_init(ifp) != 0)
	    return ENXIO;

	priv->open = cvm_oct_common_open;
	priv->stop = cvm_oct_common_stop;
	priv->stop(ifp);

	/* Due to GMX errata in CN3XXX series chips, it is necessary to take the
	   link down immediately whne the PHY changes state. In order to do this
	   we call the poll function every time the RGMII inband status changes.
	   This may cause problems if the PHY doesn't implement inband status
	   properly */
	if (number_rgmii_ports == 0) {
		sc = device_get_softc(device_get_parent(priv->dev));

		rid = 0;
		sc->sc_rgmii_irq = bus_alloc_resource(sc->sc_dev, SYS_RES_IRQ,
						      &rid, OCTEON_IRQ_RML,
						      OCTEON_IRQ_RML, 1,
						      RF_ACTIVE);
		if (sc->sc_rgmii_irq == NULL) {
			device_printf(sc->sc_dev, "could not allocate RGMII irq");
			return ENXIO;
		}

		error = bus_setup_intr(sc->sc_dev, sc->sc_rgmii_irq,
				       INTR_TYPE_NET | INTR_MPSAFE,
				       cvm_oct_rgmii_rml_interrupt, NULL,
				       &number_rgmii_ports, NULL);
		if (error != 0) {
			device_printf(sc->sc_dev, "could not setup RGMII irq");
			return error;
		}
	}
	number_rgmii_ports++;

	/* Only true RGMII ports need to be polled. In GMII mode, port 0 is really
	   a RGMII port */
	if (((priv->imode == CVMX_HELPER_INTERFACE_MODE_GMII) && (priv->port == 0)) ||
	    (priv->imode == CVMX_HELPER_INTERFACE_MODE_RGMII)) {

		if (cvmx_sysinfo_get()->board_type != CVMX_BOARD_TYPE_SIM) {

			cvmx_gmxx_rxx_int_en_t gmx_rx_int_en;
			int interface = INTERFACE(priv->port);
			int index = INDEX(priv->port);

			/* Enable interrupts on inband status changes for this port */
			gmx_rx_int_en.u64 = cvmx_read_csr(CVMX_GMXX_RXX_INT_EN(index, interface));
			gmx_rx_int_en.s.phy_dupx = 1;
			gmx_rx_int_en.s.phy_link = 1;
			gmx_rx_int_en.s.phy_spd = 1;
			cvmx_write_csr(CVMX_GMXX_RXX_INT_EN(index, interface), gmx_rx_int_en.u64);
			priv->poll = cvm_oct_rgmii_poll;
		}
	}

	return 0;
}
示例#11
0
static int cvm_oct_rgmii_rml_interrupt(void *dev_id)
{
	cvmx_npi_rsl_int_blocks_t rsl_int_blocks;
	int index;
	int return_status = FILTER_STRAY;

	rsl_int_blocks.u64 = cvmx_read_csr(CVMX_NPI_RSL_INT_BLOCKS);

	/* Check and see if this interrupt was caused by the GMX0 block */
	if (rsl_int_blocks.s.gmx0) {

		int interface = 0;
		/* Loop through every port of this interface */
		for (index = 0; index < cvmx_helper_ports_on_interface(interface); index++) {

			/* Read the GMX interrupt status bits */
			cvmx_gmxx_rxx_int_reg_t gmx_rx_int_reg;
			gmx_rx_int_reg.u64 = cvmx_read_csr(CVMX_GMXX_RXX_INT_REG(index, interface));
			gmx_rx_int_reg.u64 &= cvmx_read_csr(CVMX_GMXX_RXX_INT_EN(index, interface));
			/* Poll the port if inband status changed */
			if (gmx_rx_int_reg.s.phy_dupx || gmx_rx_int_reg.s.phy_link || gmx_rx_int_reg.s.phy_spd) {

				struct ifnet *ifp = cvm_oct_device[cvmx_helper_get_ipd_port(interface, index)];
				if (ifp)
					cvm_oct_rgmii_poll(ifp);
				gmx_rx_int_reg.u64 = 0;
				gmx_rx_int_reg.s.phy_dupx = 1;
				gmx_rx_int_reg.s.phy_link = 1;
				gmx_rx_int_reg.s.phy_spd = 1;
				cvmx_write_csr(CVMX_GMXX_RXX_INT_REG(index, interface), gmx_rx_int_reg.u64);
				return_status = FILTER_HANDLED;
			}
		}
	}

	/* Check and see if this interrupt was caused by the GMX1 block */
	if (rsl_int_blocks.s.gmx1) {

		int interface = 1;
		/* Loop through every port of this interface */
		for (index = 0; index < cvmx_helper_ports_on_interface(interface); index++) {

			/* Read the GMX interrupt status bits */
			cvmx_gmxx_rxx_int_reg_t gmx_rx_int_reg;
			gmx_rx_int_reg.u64 = cvmx_read_csr(CVMX_GMXX_RXX_INT_REG(index, interface));
			gmx_rx_int_reg.u64 &= cvmx_read_csr(CVMX_GMXX_RXX_INT_EN(index, interface));
			/* Poll the port if inband status changed */
			if (gmx_rx_int_reg.s.phy_dupx || gmx_rx_int_reg.s.phy_link || gmx_rx_int_reg.s.phy_spd) {

				struct ifnet *ifp = cvm_oct_device[cvmx_helper_get_ipd_port(interface, index)];
				if (ifp)
					cvm_oct_rgmii_poll(ifp);
				gmx_rx_int_reg.u64 = 0;
				gmx_rx_int_reg.s.phy_dupx = 1;
				gmx_rx_int_reg.s.phy_link = 1;
				gmx_rx_int_reg.s.phy_spd = 1;
				cvmx_write_csr(CVMX_GMXX_RXX_INT_REG(index, interface), gmx_rx_int_reg.u64);
				return_status = FILTER_HANDLED;
			}
		}
	}
	return return_status;
}
示例#12
0
static irqreturn_t cvm_oct_rgmii_rml_interrupt(int cpl, void *dev_id)
{
	union cvmx_npi_rsl_int_blocks rsl_int_blocks;
	int index;
	irqreturn_t return_status = IRQ_NONE;

	rsl_int_blocks.u64 = cvmx_read_csr(CVMX_NPI_RSL_INT_BLOCKS);

	
	if (rsl_int_blocks.s.gmx0) {

		int interface = 0;
		
		for (index = 0;
		     index < cvmx_helper_ports_on_interface(interface);
		     index++) {

			
			union cvmx_gmxx_rxx_int_reg gmx_rx_int_reg;
			gmx_rx_int_reg.u64 =
			    cvmx_read_csr(CVMX_GMXX_RXX_INT_REG
					  (index, interface));
			gmx_rx_int_reg.u64 &=
			    cvmx_read_csr(CVMX_GMXX_RXX_INT_EN
					  (index, interface));
			
			if (gmx_rx_int_reg.s.phy_dupx
			    || gmx_rx_int_reg.s.phy_link
			    || gmx_rx_int_reg.s.phy_spd) {

				struct net_device *dev =
				    cvm_oct_device[cvmx_helper_get_ipd_port
						   (interface, index)];
				if (dev)
					cvm_oct_rgmii_poll(dev);
				gmx_rx_int_reg.u64 = 0;
				gmx_rx_int_reg.s.phy_dupx = 1;
				gmx_rx_int_reg.s.phy_link = 1;
				gmx_rx_int_reg.s.phy_spd = 1;
				cvmx_write_csr(CVMX_GMXX_RXX_INT_REG
					       (index, interface),
					       gmx_rx_int_reg.u64);
				return_status = IRQ_HANDLED;
			}
		}
	}

	
	if (rsl_int_blocks.s.gmx1) {

		int interface = 1;
		
		for (index = 0;
		     index < cvmx_helper_ports_on_interface(interface);
		     index++) {

			
			union cvmx_gmxx_rxx_int_reg gmx_rx_int_reg;
			gmx_rx_int_reg.u64 =
			    cvmx_read_csr(CVMX_GMXX_RXX_INT_REG
					  (index, interface));
			gmx_rx_int_reg.u64 &=
			    cvmx_read_csr(CVMX_GMXX_RXX_INT_EN
					  (index, interface));
			
			if (gmx_rx_int_reg.s.phy_dupx
			    || gmx_rx_int_reg.s.phy_link
			    || gmx_rx_int_reg.s.phy_spd) {

				struct net_device *dev =
				    cvm_oct_device[cvmx_helper_get_ipd_port
						   (interface, index)];
				if (dev)
					cvm_oct_rgmii_poll(dev);
				gmx_rx_int_reg.u64 = 0;
				gmx_rx_int_reg.s.phy_dupx = 1;
				gmx_rx_int_reg.s.phy_link = 1;
				gmx_rx_int_reg.s.phy_spd = 1;
				cvmx_write_csr(CVMX_GMXX_RXX_INT_REG
					       (index, interface),
					       gmx_rx_int_reg.u64);
				return_status = IRQ_HANDLED;
			}
		}
	}
	return return_status;
}