X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=drivers%2Fnet%2Fat91_emac.c;h=4e5685c0c32b83fae2a46be6e6c33c43e9f4eacb;hb=d7b1970015e62d37b26bb6b94b64ae36728c63cc;hp=239956998dab1f59d5c44bca5c1596110860dea6;hpb=111d6c6ad15d1425d3e5a678b2ff4b593e910fca;p=u-boot diff --git a/drivers/net/at91_emac.c b/drivers/net/at91_emac.c index 239956998d..4e5685c0c3 100644 --- a/drivers/net/at91_emac.c +++ b/drivers/net/at91_emac.c @@ -53,6 +53,10 @@ Please decrease the CONFIG_SYS_RX_ETH_BUFFER value #endif +#ifndef CONFIG_DRIVER_AT91EMAC_PHYADDR +#define CONFIG_DRIVER_AT91EMAC_PHYADDR 0 +#endif + /* MDIO clock must not exceed 2.5 MHz, so enable MCK divider */ #if (AT91C_MASTER_CLOCK > 80000000) #define HCLK_DIV AT91_EMAC_CFG_MCLK_64 @@ -123,13 +127,19 @@ void at91emac_DisableMDIO(at91_emac_t *at91mac) int at91emac_read(at91_emac_t *at91mac, unsigned char addr, unsigned char reg, unsigned short *value) { + unsigned long netstat; at91emac_EnableMDIO(at91mac); writel(AT91_EMAC_MAN_HIGH | AT91_EMAC_MAN_RW_R | AT91_EMAC_MAN_REGA(reg) | AT91_EMAC_MAN_CODE_802_3 | AT91_EMAC_MAN_PHYA(addr), &at91mac->man); - udelay(10000); + + do { + netstat = readl(&at91mac->sr); + DEBUG_AT91PHY("poll SR %08lx\n", netstat); + } while (!(netstat & AT91_EMAC_SR_IDLE)); + *value = readl(&at91mac->man) & AT91_EMAC_MAN_DATA_MASK; at91emac_DisableMDIO(at91mac); @@ -142,6 +152,7 @@ int at91emac_read(at91_emac_t *at91mac, unsigned char addr, int at91emac_write(at91_emac_t *at91mac, unsigned char addr, unsigned char reg, unsigned short value) { + unsigned long netstat; DEBUG_AT91PHY("AT91PHY write %x REG(%d)=%x\n", at91mac, reg, &value) at91emac_EnableMDIO(at91mac); @@ -150,15 +161,20 @@ int at91emac_write(at91_emac_t *at91mac, unsigned char addr, AT91_EMAC_MAN_REGA(reg) | AT91_EMAC_MAN_CODE_802_3 | AT91_EMAC_MAN_PHYA(addr) | (value & AT91_EMAC_MAN_DATA_MASK), &at91mac->man); - udelay(10000); + + do { + netstat = readl(&at91mac->sr); + DEBUG_AT91PHY("poll SR %08lx\n", netstat); + } while (!(netstat & AT91_EMAC_SR_IDLE)); at91emac_DisableMDIO(at91mac); + return 0; } #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) -at91_emac_t *get_emacbase_by_name(char *devname) +at91_emac_t *get_emacbase_by_name(const char *devname) { struct eth_device *netdev; @@ -166,7 +182,7 @@ at91_emac_t *get_emacbase_by_name(char *devname) return (at91_emac_t *) netdev->iobase; } -int at91emac_mii_read(char *devname, unsigned char addr, +int at91emac_mii_read(const char *devname, unsigned char addr, unsigned char reg, unsigned short *value) { at91_emac_t *emac; @@ -177,7 +193,7 @@ int at91emac_mii_read(char *devname, unsigned char addr, } -int at91emac_mii_write(char *devname, unsigned char addr, +int at91emac_mii_write(const char *devname, unsigned char addr, unsigned char reg, unsigned short value) { at91_emac_t *emac; @@ -198,12 +214,15 @@ static int at91emac_phy_reset(struct eth_device *netdev) emac = (at91_emac_t *) netdev->iobase; adv = ADVERTISE_CSMA | ADVERTISE_ALL; - at91emac_write(emac, 0, MII_ADVERTISE, adv); + at91emac_write(emac, CONFIG_DRIVER_AT91EMAC_PHYADDR, + MII_ADVERTISE, adv); VERBOSEP("%s: Starting autonegotiation...\n", netdev->name); - at91emac_write(emac, 0, MII_BMCR, (BMCR_ANENABLE | BMCR_ANRESTART)); + at91emac_write(emac, CONFIG_DRIVER_AT91EMAC_PHYADDR, MII_BMCR, + (BMCR_ANENABLE | BMCR_ANRESTART)); - for (i = 0; i < 100000 / 100; i++) { - at91emac_read(emac, 0, MII_BMSR, &status); + for (i = 0; i < 30000; i++) { + at91emac_read(emac, CONFIG_DRIVER_AT91EMAC_PHYADDR, + MII_BMSR, &status); if (status & BMSR_ANEGCOMPLETE) break; udelay(100); @@ -214,7 +233,7 @@ static int at91emac_phy_reset(struct eth_device *netdev) } else { printf("%s: Autonegotiation timed out (status=0x%04x)\n", netdev->name, status); - return 1; + return -1; } return 0; } @@ -229,21 +248,24 @@ static int at91emac_phy_init(struct eth_device *netdev) emac = (at91_emac_t *) netdev->iobase; /* Check if the PHY is up to snuff... */ - at91emac_read(emac, 0, MII_PHYSID1, &phy_id); + at91emac_read(emac, CONFIG_DRIVER_AT91EMAC_PHYADDR, + MII_PHYSID1, &phy_id); if (phy_id == 0xffff) { printf("%s: No PHY present\n", netdev->name); - return 1; + return -1; } - at91emac_read(emac, 0, MII_BMSR, &status); + at91emac_read(emac, CONFIG_DRIVER_AT91EMAC_PHYADDR, + MII_BMSR, &status); if (!(status & BMSR_LSTATUS)) { /* Try to re-negotiate if we don't have link already. */ if (at91emac_phy_reset(netdev)) - return 2; + return -2; for (i = 0; i < 100000 / 100; i++) { - at91emac_read(emac, 0, MII_BMSR, &status); + at91emac_read(emac, CONFIG_DRIVER_AT91EMAC_PHYADDR, + MII_BMSR, &status); if (status & BMSR_LSTATUS) break; udelay(100); @@ -251,10 +273,12 @@ static int at91emac_phy_init(struct eth_device *netdev) } if (!(status & BMSR_LSTATUS)) { VERBOSEP("%s: link down\n", netdev->name); - return 3; + return -3; } else { - at91emac_read(emac, 0, MII_ADVERTISE, &adv); - at91emac_read(emac, 0, MII_LPA, &lpa); + at91emac_read(emac, CONFIG_DRIVER_AT91EMAC_PHYADDR, + MII_ADVERTISE, &adv); + at91emac_read(emac, CONFIG_DRIVER_AT91EMAC_PHYADDR, + MII_LPA, &lpa); media = mii_nway_result(lpa & adv); speed = (media & (ADVERTISE_100FULL | ADVERTISE_100HALF) ? 1 : 0); @@ -271,10 +295,10 @@ int at91emac_UpdateLinkSpeed(at91_emac_t *emac) { unsigned short stat1; - at91emac_read(emac, 0, MII_BMSR, &stat1); + at91emac_read(emac, CONFIG_DRIVER_AT91EMAC_PHYADDR, MII_BMSR, &stat1); if (!(stat1 & BMSR_LSTATUS)) /* link status up? */ - return 1; + return -1; if (stat1 & BMSR_100FULL) { /*set Emac for 100BaseTX and Full Duplex */ @@ -309,7 +333,7 @@ int at91emac_UpdateLinkSpeed(at91_emac_t *emac) &emac->cfg); return 0; } - return 1; + return 0; } static int at91emac_init(struct eth_device *netdev, bd_t *bd) @@ -348,14 +372,6 @@ static int at91emac_init(struct eth_device *netdev, bd_t *bd) writel(1 << AT91_ID_EMAC, &pmc->pcer); writel(readl(&emac->ctl) | AT91_EMAC_CTL_CSR, &emac->ctl); - DEBUG_AT91EMAC("init MAC-ADDR %x%x \n", - cpu_to_le16(*((u16 *)(netdev->enetaddr + 4))), - cpu_to_le32(*((u32 *)netdev->enetaddr))); - writel(cpu_to_le32(*((u32 *)netdev->enetaddr)), &emac->sa2l); - writel(cpu_to_le16(*((u16 *)(netdev->enetaddr + 4))), &emac->sa2h); - DEBUG_AT91EMAC("init MAC-ADDR %x%x \n", - readl(&emac->sa2h), readl(&emac->sa2l)); - /* Init Ethernet buffers */ for (i = 0; i < RBF_FRAMEMAX; i++) { dev->rbfdt[i].addr = (unsigned long) NetRxPackets[i]; @@ -372,7 +388,7 @@ static int at91emac_init(struct eth_device *netdev, bd_t *bd) value = AT91_EMAC_CFG_CAF | AT91_EMAC_CFG_NBC | HCLK_DIV; #ifdef CONFIG_RMII - value |= AT91C_EMAC_RMII; + value |= AT91_EMAC_CFG_RMII; #endif writel(value, &emac->cfg); @@ -383,7 +399,7 @@ static int at91emac_init(struct eth_device *netdev, bd_t *bd) at91emac_UpdateLinkSpeed(emac); return 0; } - return 1; + return -1; } static void at91emac_halt(struct eth_device *netdev) @@ -456,6 +472,25 @@ static int at91emac_recv(struct eth_device *netdev) return 0; } +static int at91emac_write_hwaddr(struct eth_device *netdev) +{ + emac_device *dev; + at91_emac_t *emac; + at91_pmc_t *pmc = (at91_pmc_t *) AT91_PMC_BASE; + emac = (at91_emac_t *) netdev->iobase; + dev = (emac_device *) netdev->priv; + + writel(1 << AT91_ID_EMAC, &pmc->pcer); + DEBUG_AT91EMAC("init MAC-ADDR %x%x \n", + cpu_to_le16(*((u16 *)(netdev->enetaddr + 4))), + cpu_to_le32(*((u32 *)netdev->enetaddr))); + writel(cpu_to_le32(*((u32 *)netdev->enetaddr)), &emac->sa2l); + writel(cpu_to_le16(*((u16 *)(netdev->enetaddr + 4))), &emac->sa2h); + DEBUG_AT91EMAC("init MAC-ADDR %x%x \n", + readl(&emac->sa2h), readl(&emac->sa2l)); + return 0; +} + int at91emac_register(bd_t *bis, unsigned long iobase) { emac_device *emac; @@ -466,28 +501,25 @@ int at91emac_register(bd_t *bis, unsigned long iobase) iobase = AT91_EMAC_BASE; emac = malloc(sizeof(*emac)+512); if (emac == NULL) - return 1; + return -1; dev = malloc(sizeof(*dev)); if (dev == NULL) { free(emac); - return 1; + return -1; } /* alignment as per Errata (64 bytes) is insufficient! */ emacfix = (emac_device *) (((unsigned long) emac + 0x1ff) & 0xFFFFFE00); memset(emacfix, 0, sizeof(emac_device)); memset(dev, 0, sizeof(*dev)); -#ifndef CONFIG_RMII - sprintf(dev->name, "AT91 EMAC"); -#else - sprintf(dev->name, "AT91 EMAC RMII"); -#endif + sprintf(dev->name, "emac"); dev->iobase = iobase; dev->priv = emacfix; dev->init = at91emac_init; dev->halt = at91emac_halt; dev->send = at91emac_send; dev->recv = at91emac_recv; + dev->write_hwaddr = at91emac_write_hwaddr; eth_register(dev);