static void
na_mii_reset(struct net_device *dev)
{
	struct netarmeth_dev *na_dev;

	NA_PRINTK("na_mii_reset\n");

	if (dev == NULL) {
		NA_PRINTK("na_mii_reset - NULL parameter\n");
		return;
	}
	na_dev = dev->priv;

	na_dev->phy_type = na_mii_identify_phy();
	if ((na_dev->phy_type != NA_ENABLE_PHY) &&
	    (na_dev->phy_type != NA_HOME_PHY)) {
		printk(KERN_WARNING "%s:  Found other than Enable, Lucent or Home PHY.\n", dev->name);
	}

	/* select appropriate Control register */
	if (na_dev->phy_type == NA_HOME_PHY)
		outl_t(0x100, get_eth_reg_addr(NETARM_ETH_MII_ADDR));
	else
		outl_t(0x400, get_eth_reg_addr(NETARM_ETH_MII_ADDR));

	outl_t(0x8000, get_eth_reg_addr(NETARM_ETH_MII_WRITE));
	na_mii_poll_busy();

	outl_t(0, get_eth_reg_addr(NETARM_ETH_MII_WRITE));
	na_mii_poll_busy();
}
static unsigned long
na_mii_negotiate(struct netarmeth_dev *na_dev)
{
	unsigned long start_time, current_time;
	unsigned long read_data;

	NA_PRINTK("na_mii_negotiate\n");

	/* Select Autonegotiation Advertisement register */
	if (na_dev->phy_type == NA_HOME_PHY)
		outl_t(0x101, get_eth_reg_addr(NETARM_ETH_MII_ADDR));
	else
		outl_t(0x404, get_eth_reg_addr(NETARM_ETH_MII_ADDR));

	/* Enable auto-negotiation */
	outl_t(0x01E1, get_eth_reg_addr(NETARM_ETH_MII_WRITE));
	na_mii_poll_busy();

	/* Select Control register */
	if (na_dev->phy_type == NA_HOME_PHY)
		outl_t(0x100, get_eth_reg_addr(NETARM_ETH_MII_ADDR));
	else
		outl_t(0x400, get_eth_reg_addr(NETARM_ETH_MII_ADDR));

	/* Restart auto-negotiation */
	outl_t(0x1200, get_eth_reg_addr(NETARM_ETH_MII_WRITE));
	na_mii_poll_busy();

	// Wait for auto-negotiation to complete or for predefined delay to elapse.

	start_time = current_time = jiffies;
	do {
		/* Select Status register */
		if (na_dev->phy_type == NA_HOME_PHY)
			outl_t(0x101, get_eth_reg_addr(NETARM_ETH_MII_ADDR));
		else
			outl_t(0x401, get_eth_reg_addr(NETARM_ETH_MII_ADDR));

		outl_t((inl_t(get_eth_reg_addr(NETARM_ETH_MII_CMD))
		        | NETARM_ETH_MIIC_RSTAT),
		       get_eth_reg_addr(NETARM_ETH_MII_CMD));
		na_mii_poll_busy();

		read_data = inl_t(get_eth_reg_addr(NETARM_ETH_MII_READ));
		if ((read_data & 0x0024) == 0x0024) {
			return (0);
		}
		current_time = jiffies;
	} while (current_time < start_time + NA_MII_NEGOTIATE_DELAY);

	NA_PRINTK("  MII negotiation delay elapsed\n");
	return (1);
}
static na_phy_type
na_mii_identify_phy(void)
{
	int id_reg_a, id_reg_b;

	NA_PRINTK("na_mii_identify_phy\n");

	/* check for Enable PHY */
	outl_t(0x402, get_eth_reg_addr(NETARM_ETH_MII_ADDR));
	outl_t((inl_t(get_eth_reg_addr(NETARM_ETH_MII_CMD)) | NETARM_ETH_MIIC_RSTAT),
	       get_eth_reg_addr(NETARM_ETH_MII_CMD));
	na_mii_poll_busy();
	id_reg_a = inl_t(get_eth_reg_addr(NETARM_ETH_MII_READ));

	if (id_reg_a == 0x0043) {
		/* This must be an Enable or a Lucent LU3X31 PHY chip */
		NA_PRINTK("  Enable PHY\n");
		return (NA_ENABLE_PHY);
	}

	/* check for AMD 79C901 HomePHY */
	outl_t(0x102, get_eth_reg_addr(NETARM_ETH_MII_ADDR));
	outl_t((inl_t(get_eth_reg_addr(NETARM_ETH_MII_CMD)) | NETARM_ETH_MIIC_RSTAT),
	       get_eth_reg_addr(NETARM_ETH_MII_CMD));
	na_mii_poll_busy();
	id_reg_a = inl_t(get_eth_reg_addr(NETARM_ETH_MII_READ));

	outl_t(0x103, get_eth_reg_addr(NETARM_ETH_MII_ADDR));
	outl_t((inl_t(get_eth_reg_addr(NETARM_ETH_MII_CMD)) | NETARM_ETH_MIIC_RSTAT),
	       get_eth_reg_addr(NETARM_ETH_MII_CMD));
	na_mii_poll_busy();
	id_reg_b = inl_t(get_eth_reg_addr(NETARM_ETH_MII_READ));

	if ((id_reg_a == 0x0000) && (id_reg_b == 0x6b71)) {
		/* This must be an AMD Home PHY chip */
		NA_PRINTK("  Home PHY\n");
		return (NA_HOME_PHY);
	}

	/* else, i.e. default */
	NA_PRINTK("  Level 1 PHY\n");
	return (NA_LEVEL1_PHY);
}
Ejemplo n.º 4
0
static void na_mii_write (int reg, int value)
{
	int mii_addr;

	/* Select register */
	mii_addr = CFG_ETH_PHY_ADDR + reg;
	SET_EADDR (NETARM_ETH_MII_ADDR, mii_addr);
	/* Write value */
	SET_EADDR (NETARM_ETH_MII_WRITE, value);
	na_mii_poll_busy ();
}
static unsigned long
na_mii_check_speed(struct netarmeth_dev *na_dev)
{
	// Check link status.  If 0, default to 100 Mbps.
	NA_PRINTK("na_mii_check_speed\n");

	if (na_dev->phy_type == NA_HOME_PHY) {
		/* The AMD Home PHY only supports 10 Mbps anyway */
		NA_PRINTK("  returning NA_10MBPS (HomePHY)\n");
		na_dev->media_100BaseT = NA_10MBPS;
	} else {
		/* Read Status register */
		outl_t(0x401, get_eth_reg_addr(NETARM_ETH_MII_ADDR));
		outl_t((inl_t(get_eth_reg_addr(NETARM_ETH_MII_CMD)) | NETARM_ETH_MIIC_RSTAT),
		       get_eth_reg_addr(NETARM_ETH_MII_CMD));
		na_mii_poll_busy();

		if ((inl_t(get_eth_reg_addr(NETARM_ETH_MII_READ)) & 0x0004) == 0) {
			NA_PRINTK("  returning NA_100MBPS (link is down)\n");
			na_dev->media_100BaseT = NA_100MBPS;
		} else {
			/* Now it's OK to check the normal speed status */
			outl_t(0x417, get_eth_reg_addr(NETARM_ETH_MII_ADDR));
			outl_t((inl_t(get_eth_reg_addr(NETARM_ETH_MII_CMD)) | NETARM_ETH_MIIC_RSTAT),
			       get_eth_reg_addr(NETARM_ETH_MII_CMD));
			na_mii_poll_busy();

			if ((inl_t(get_eth_reg_addr(NETARM_ETH_MII_READ)) & 0x0200) != 0) {
				NA_PRINTK("  returning NA_100MBPS (b)\n");
				na_dev->media_100BaseT = NA_100MBPS;
			} else {
				NA_PRINTK("  returning NA_10MBPS\n");
				na_dev->media_100BaseT = NA_10MBPS;
			}
		}
	}
	return(na_dev->media_100BaseT);
}
Ejemplo n.º 6
0
static unsigned int na_mii_read (int reg)
{
	int mii_addr, val;

	/* Select register */
	mii_addr = CFG_ETH_PHY_ADDR + reg;
	SET_EADDR (NETARM_ETH_MII_ADDR, mii_addr);
	/* do one management cycle */
	SET_EADDR (NETARM_ETH_MII_CMD,
		   GET_EADDR (NETARM_ETH_MII_CMD) | NETARM_ETH_MIIC_RSTAT);
	na_mii_poll_busy ();
	/* Return read value */
	val = GET_EADDR (NETARM_ETH_MII_READ);
	return val;
}