static void read_phy(unsigned char phy_addr, unsigned char address, unsigned int *value) { at91_emac_write(AT91_EMAC_MAN, AT91_EMAC_MAN_802_3 | AT91_EMAC_RW_R | ((phy_addr & 0x1f) << 23) | (address << 18)); /* Wait until IDLE bit in Network Status register is cleared */ at91_phy_wait(); *value = at91_emac_read(AT91_EMAC_MAN) & AT91_EMAC_DATA; }
static void read_phy(unsigned char phy_addr, unsigned char address, unsigned int *value) { at91_emac_write(AT91_EMAC_MAN, AT91_EMAC_MAN_802_3 | AT91_EMAC_RW_R | ((phy_addr & 0x1f) << 23) | (address << 18)); at91_phy_wait(); *value = at91_emac_read(AT91_EMAC_MAN) & AT91_EMAC_DATA; }
static int at91_ether_mii_write(struct mii_bus *dev, int addr, int reg, u16 val) { int ret; enable_mdi(); at91_emac_write(AT91_EMAC_MAN, AT91_EMAC_MAN_802_3 | AT91_EMAC_RW_W | ((addr & 0x1f) << 23) | (reg << 18) | (val & AT91_EMAC_DATA)); /* Wait until IDLE bit in Network Status register is cleared */ ret = at91_phy_wait(); disable_mdi(); return ret; }
/* * Access the PHY to determine the current link speed and mode, and update the * MAC accordingly. * If no link or auto-negotiation is busy, then no changes are made. */ static void update_linkspeed(struct net_device *dev, int silent) { struct at91_private *lp = netdev_priv(dev); unsigned int bmsr, bmcr, lpa, mac_cfg; unsigned int speed, duplex; if (!mii_link_ok(&lp->mii)) { /* no link */ netif_carrier_off(dev); if (!silent) printk(KERN_INFO "%s: Link down.\n", dev->name); return; } /* Link up, or auto-negotiation still in progress */ read_phy(lp->phy_address, MII_BMSR, &bmsr); read_phy(lp->phy_address, MII_BMCR, &bmcr); if (bmcr & BMCR_ANENABLE) { /* AutoNegotiation is enabled */ if (!(bmsr & BMSR_ANEGCOMPLETE)) return; /* Do nothing - another interrupt generated when negotiation complete */ read_phy(lp->phy_address, MII_LPA, &lpa); if ((lpa & LPA_100FULL) || (lpa & LPA_100HALF)) speed = SPEED_100; else speed = SPEED_10; if ((lpa & LPA_100FULL) || (lpa & LPA_10FULL)) duplex = DUPLEX_FULL; else duplex = DUPLEX_HALF; } else { speed = (bmcr & BMCR_SPEED100) ? SPEED_100 : SPEED_10; duplex = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF; } /* Update the MAC */ mac_cfg = at91_emac_read(AT91_EMAC_CFG) & ~(AT91_EMAC_SPD | AT91_EMAC_FD); if (speed == SPEED_100) { if (duplex == DUPLEX_FULL) /* 100 Full Duplex */ mac_cfg |= AT91_EMAC_SPD | AT91_EMAC_FD; else /* 100 Half Duplex */ mac_cfg |= AT91_EMAC_SPD; } else { if (duplex == DUPLEX_FULL) /* 10 Full Duplex */ mac_cfg |= AT91_EMAC_FD; else {} /* 10 Half Duplex */ } at91_emac_write(AT91_EMAC_CFG, mac_cfg); if (!silent) printk(KERN_INFO "%s: Link now %i-%s\n", dev->name, speed, (duplex == DUPLEX_FULL) ? "FullDuplex" : "HalfDuplex"); netif_carrier_on(dev); }
static void update_linkspeed(struct net_device *dev, int silent) { struct at91_private *lp = netdev_priv(dev); unsigned int bmsr, bmcr, lpa, mac_cfg; unsigned int speed, duplex; if (!mii_link_ok(&lp->mii)) { netif_carrier_off(dev); if (!silent) printk(KERN_INFO "%s: Link down.\n", dev->name); return; } read_phy(lp->phy_address, MII_BMSR, &bmsr); read_phy(lp->phy_address, MII_BMCR, &bmcr); if (bmcr & BMCR_ANENABLE) { if (!(bmsr & BMSR_ANEGCOMPLETE)) return; read_phy(lp->phy_address, MII_LPA, &lpa); if ((lpa & LPA_100FULL) || (lpa & LPA_100HALF)) speed = SPEED_100; else speed = SPEED_10; if ((lpa & LPA_100FULL) || (lpa & LPA_10FULL)) duplex = DUPLEX_FULL; else duplex = DUPLEX_HALF; } else { speed = (bmcr & BMCR_SPEED100) ? SPEED_100 : SPEED_10; duplex = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF; } mac_cfg = at91_emac_read(AT91_EMAC_CFG) & ~(AT91_EMAC_SPD | AT91_EMAC_FD); if (speed == SPEED_100) { if (duplex == DUPLEX_FULL) mac_cfg |= AT91_EMAC_SPD | AT91_EMAC_FD; else mac_cfg |= AT91_EMAC_SPD; } else { if (duplex == DUPLEX_FULL) mac_cfg |= AT91_EMAC_FD; else {} } at91_emac_write(AT91_EMAC_CFG, mac_cfg); if (!silent) printk(KERN_INFO "%s: Link now %i-%s\n", dev->name, speed, (duplex == DUPLEX_FULL) ? "FullDuplex" : "HalfDuplex"); netif_carrier_on(dev); }
static void update_linkspeed(struct eth_device *edev) { unsigned int mac_cfg; /* Update the MAC */ mac_cfg = at91_emac_read(AT91_EMAC_CFG) & ~(AT91_EMAC_SPD | AT91_EMAC_FD); if (edev->phydev->speed == SPEED_100) { if (edev->phydev->duplex) mac_cfg |= AT91_EMAC_SPD | AT91_EMAC_FD; else /* 100 Half Duplex */ mac_cfg |= AT91_EMAC_SPD; } else { if (edev->phydev->duplex) mac_cfg |= AT91_EMAC_FD; else {} /* 10 Half Duplex */ } at91_emac_write(AT91_EMAC_CFG, mac_cfg); }
static int at91_ether_mii_read(struct mii_bus *dev, int addr, int reg) { int value; enable_mdi(); at91_emac_write(AT91_EMAC_MAN, AT91_EMAC_MAN_802_3 | AT91_EMAC_RW_R | ((addr & 0x1f) << 23) | (reg << 18)); /* Wait until IDLE bit in Network Status register is cleared */ value = at91_phy_wait(); if (value < 0) goto out; value = at91_emac_read(AT91_EMAC_MAN) & AT91_EMAC_DATA; out: disable_mdi(); return value; }
static int at91_ether_rx(struct eth_device *edev) { struct ether_device *etdev = to_ether(edev); int size; struct rbf_t *rbfp = etdev->rbfp; if (!(rbfp->addr & RBF_OWNER)) return 0; size = rbfp->size & RBF_SIZE; net_receive(edev, (unsigned char *)(rbfp->addr & RBF_ADDR), size); rbfp->addr &= ~RBF_OWNER; if (rbfp->addr & RBF_WRAP) etdev->rbfp = etdev->rbfdt; else etdev->rbfp++; at91_emac_write(AT91_EMAC_RSR, at91_emac_read(AT91_EMAC_RSR) | AT91_EMAC_RSR_REC); return size; }
static int at91_ether_probe(struct device_d *dev) { unsigned int mac_cfg; struct ether_device *ether_dev; struct eth_device *edev; struct mii_bus *miibus; unsigned long ether_hz; struct clk *pclk; struct macb_platform_data *pdata; if (!dev->platform_data) { printf("at91_ether: no platform_data\n"); return -ENODEV; } pdata = dev->platform_data; ether_dev = xzalloc(sizeof(struct ether_device)); edev = ðer_dev->netdev; miibus = ðer_dev->miibus; edev->priv = ether_dev; edev->init = at91_ether_init; edev->open = at91_ether_open; edev->send = at91_ether_send; edev->recv = at91_ether_rx; edev->halt = at91_ether_halt; edev->get_ethaddr = at91_ether_get_ethaddr; edev->set_ethaddr = at91_ether_set_ethaddr; ether_dev->rbf_framebuf = dma_alloc_coherent(MAX_RX_DESCR * MAX_RBUFF_SZ); ether_dev->rbfdt = dma_alloc_coherent(sizeof(struct rbf_t) * MAX_RX_DESCR); ether_dev->phy_addr = pdata->phy_addr; miibus->read = at91_ether_mii_read; miibus->write = at91_ether_mii_write; /* Sanitize the clocks */ mac_cfg = at91_emac_read(AT91_EMAC_CFG); pclk = clk_get(dev, "ether_clk"); clk_enable(pclk); ether_hz = clk_get_rate(pclk); if (ether_hz > 40000000) { /* MDIO clock must not exceed 2.5 MHz, so enable MCK divider */ mac_cfg |= AT91_EMAC_CLK_DIV64; } else { mac_cfg &= ~AT91_EMAC_CLK; } mac_cfg |= AT91_EMAC_CLK_DIV32 | AT91_EMAC_BIG; if (pdata->phy_interface == PHY_INTERFACE_MODE_RMII) { ether_dev->interface = PHY_INTERFACE_MODE_RGMII; mac_cfg |= AT91_EMAC_RMII; } else { ether_dev->interface = PHY_INTERFACE_MODE_MII; } at91_emac_write(AT91_EMAC_CFG, mac_cfg); mdiobus_register(miibus); eth_register(edev); return 0; }