Ejemplo n.º 1
0
/*
 * External interrupt handler for boards using elmer0.
 */
int t1_elmer0_ext_intr_handler(adapter_t *adapter)
{
	struct cphy *phy;
	int phy_cause;
	u32 cause;

	t1_tpi_read(adapter, A_ELMER0_INT_CAUSE, &cause);

	switch (board_info(adapter)->board) {
#ifdef CONFIG_CHELSIO_T1_1G
	case CHBT_BOARD_CHT204:
	case CHBT_BOARD_CHT204E:
	case CHBT_BOARD_CHN204:
	case CHBT_BOARD_CHT204V: {
		int i, port_bit;
		for_each_port(adapter, i) {
			port_bit = i + 1;
			if (!(cause & (1 << port_bit)))
				continue;

			phy = adapter->port[i].phy;
			phy_cause = phy->ops->interrupt_handler(phy);
			if (phy_cause & cphy_cause_link_change)
				t1_link_changed(adapter, i);
		}
		break;
	}
	case CHBT_BOARD_CHT101:
		if (cause & ELMER0_GP_BIT1) { /* Marvell 88E1111 interrupt */
			phy = adapter->port[0].phy;
			phy_cause = phy->ops->interrupt_handler(phy);
			if (phy_cause & cphy_cause_link_change)
				t1_link_changed(adapter, 0);
		}
		break;
	case CHBT_BOARD_7500: {
		int p;
		/*
		 * Elmer0's interrupt cause isn't useful here because there is
		 * only one bit that can be set for all 4 ports.  This means
		 * we are forced to check every PHY's interrupt status
		 * register to see who initiated the interrupt.
		 */
		for_each_port(adapter, p) {
			phy = adapter->port[p].phy;
			phy_cause = phy->ops->interrupt_handler(phy);
			if (phy_cause & cphy_cause_link_change)
			    t1_link_changed(adapter, p);
		}
		break;
	}
Ejemplo n.º 2
0
static int my3126_interrupt_handler(struct cphy *cphy)
{
	u32 val;
	u16 val16;
	u16 status;
	u32 act_count;
	adapter_t *adapter;
	adapter = cphy->adapter;

	if (cphy->count == 50) {
		mdio_read(cphy, 0x1, 0x1, &val);
		val16 = (u16) val;
		status = cphy->bmsr ^ val16;

		if (status & BMSR_LSTATUS)
			t1_link_changed(adapter, 0);
		cphy->bmsr = val16;

		/* We have only enabled link change interrupts so it
		   must be that
		 */
		cphy->count = 0;
	}

	t1_tpi_write(adapter, OFFSET(SUNI1x10GEXP_REG_MSTAT_CONTROL),
		SUNI1x10GEXP_BITMSK_MSTAT_SNAP);
	t1_tpi_read(adapter,
		OFFSET(SUNI1x10GEXP_REG_MSTAT_COUNTER_1_LOW), &act_count);
	t1_tpi_read(adapter,
		OFFSET(SUNI1x10GEXP_REG_MSTAT_COUNTER_33_LOW), &val);
	act_count += val;

	/* Populate elmer_gpo with the register value */
	t1_tpi_read(adapter, A_ELMER0_GPO, &val);
	cphy->elmer_gpo = val;

	if ( (val & (1 << 8)) || (val & (1 << 19)) ||
	     (cphy->act_count == act_count) || cphy->act_on ) {
		if (is_T2(adapter))
			val |= (1 << 9);
		else if (t1_is_T1B(adapter))
			val |= (1 << 20);
		cphy->act_on = 0;
	} else {
		if (is_T2(adapter))
			val &= ~(1 << 9);
		else if (t1_is_T1B(adapter))
			val &= ~(1 << 20);
		cphy->act_on = 1;
	}

	t1_tpi_write(adapter, A_ELMER0_GPO, val);

	cphy->elmer_gpo = val;
	cphy->act_count = act_count;
	cphy->count++;

	return cphy_cause_link_change;
}
Ejemplo n.º 3
0
int t1_elmer0_ext_intr_handler(adapter_t *adapter)
{
	struct cphy *phy;
	int phy_cause;
	u32 cause;

	t1_tpi_read(adapter, A_ELMER0_INT_CAUSE, &cause);

	switch (board_info(adapter)->board) {
#ifdef CONFIG_CHELSIO_T1_1G
	case CHBT_BOARD_CHT204:
	case CHBT_BOARD_CHT204E:
	case CHBT_BOARD_CHN204:
	case CHBT_BOARD_CHT204V: {
		int i, port_bit;
		for_each_port(adapter, i) {
			port_bit = i + 1;
			if (!(cause & (1 << port_bit)))
				continue;

			phy = adapter->port[i].phy;
			phy_cause = phy->ops->interrupt_handler(phy);
			if (phy_cause & cphy_cause_link_change)
				t1_link_changed(adapter, i);
		}
		break;
	}
	case CHBT_BOARD_CHT101:
		if (cause & ELMER0_GP_BIT1) { 
			phy = adapter->port[0].phy;
			phy_cause = phy->ops->interrupt_handler(phy);
			if (phy_cause & cphy_cause_link_change)
				t1_link_changed(adapter, 0);
		}
		break;
	case CHBT_BOARD_7500: {
		int p;
		
		for_each_port(adapter, p) {
			phy = adapter->port[p].phy;
			phy_cause = phy->ops->interrupt_handler(phy);
			if (phy_cause & cphy_cause_link_change)
			    t1_link_changed(adapter, p);
		}
		break;
	}
Ejemplo n.º 4
0
static int pm3393_enable_port(struct cmac *cmac, int which)
{
	
	pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_CONTROL,
		SUNI1x10GEXP_BITMSK_MSTAT_CLEAR);
	udelay(2);
	memset(&cmac->stats, 0, sizeof(struct cmac_statistics));

	pm3393_enable(cmac, which);

	t1_link_changed(cmac->adapter, 0);
	return 0;
}
Ejemplo n.º 5
0
/*
 * PHY interrupt handler for FPGA boards.
 */
static int fpga_phy_intr_handler(adapter_t *adapter)
{
	int p;
	u32 cause = readl(adapter->regs + FPGA_GMAC_ADDR_INTERRUPT_CAUSE);

	for_each_port(adapter, p)
		if (cause & (1 << p)) {
			struct cphy *phy = adapter->port[p].phy;
			int phy_cause = phy->ops->interrupt_handler(phy);

			if (phy_cause & cphy_cause_link_change)
				t1_link_changed(adapter, p);
		}
	writel(cause, adapter->regs + FPGA_GMAC_ADDR_INTERRUPT_CAUSE);
	return 0;
}
Ejemplo n.º 6
0
static int pm3393_enable_port(struct cmac *cmac, int which)
{
	/* Clear port statistics */
	pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_CONTROL,
		SUNI1x10GEXP_BITMSK_MSTAT_CLEAR);
	udelay(2);
	memset(&cmac->stats, 0, sizeof(struct cmac_statistics));

	pm3393_enable(cmac, which);

	/*
	 * XXX This should be done by the PHY and preferably not at all.
	 * The PHY doesn't give us link status indication on its own so have
	 * the link management code query it instead.
	 */
	t1_link_changed(cmac->adapter, 0);
	return 0;
}
Ejemplo n.º 7
0
/*
 * Called when a port's link settings change to propagate the new values to the
 * associated PHY and MAC.  After performing the common tasks it invokes an
 * OS-specific handler.
 */
/* static */ void link_changed(adapter_t *adapter, int port_id)
{
	int link_ok, speed, duplex, fc;
	struct cphy *phy = adapter->port[port_id].phy;
	struct link_config *lc = &adapter->port[port_id].link_config;

	phy->ops->get_link_status(phy, &link_ok, &speed, &duplex, &fc);

	lc->speed = speed < 0 ? SPEED_INVALID : speed;
	lc->duplex = duplex < 0 ? DUPLEX_INVALID : duplex;
	if (!(lc->requested_fc & PAUSE_AUTONEG))
		fc = lc->requested_fc & (PAUSE_RX | PAUSE_TX);

	if (link_ok && speed >= 0 && lc->autoneg == AUTONEG_ENABLE) {
		/* Set MAC speed, duplex, and flow control to match PHY. */
		struct cmac *mac = adapter->port[port_id].mac;

		mac->ops->set_speed_duplex_fc(mac, speed, duplex, fc);
		lc->fc = (unsigned char)fc;
	}
	t1_link_changed(adapter, port_id, link_ok, speed, duplex, fc);
}