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); }
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); }
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; }