X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fat91_emac.c;h=be3d82e67eaccb9dd76c111263856215bdccc665;hb=5a49f17481bb9dcab1431c663d35cc1cace16825;hp=245da121b94d520e12eb562641c12945ae6aaa8c;hpb=d6f324d03d7829a1da1dee8b60f91b173a3976f0;p=oweals%2Fu-boot.git diff --git a/drivers/net/at91_emac.c b/drivers/net/at91_emac.c index 245da121b9..be3d82e67e 100644 --- a/drivers/net/at91_emac.c +++ b/drivers/net/at91_emac.c @@ -5,40 +5,15 @@ * (C) Copyright 2003 * Author : Hamid Ikdoumi (Atmel) - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA + * SPDX-License-Identifier: GPL-2.0+ */ #include #include -#ifndef CONFIG_AT91_LEGACY #include #include -#include +#include #include -#else -/* remove next 5 lines, if all RM9200 boards convert to at91 arch */ -#include -#include -#include -#include -#include -#endif #include #include #include @@ -69,21 +44,21 @@ #endif #ifdef ET_DEBUG -#define DEBUG_AT91EMAC(...) printf(__VA_ARGS__); +#define DEBUG_AT91EMAC 1 #else -#define DEBUG_AT91EMAC(...) +#define DEBUG_AT91EMAC 0 #endif #ifdef MII_DEBUG -#define DEBUG_AT91PHY(...) printf(__VA_ARGS__); +#define DEBUG_AT91PHY 1 #else -#define DEBUG_AT91PHY(...) +#define DEBUG_AT91PHY 0 #endif #ifndef CONFIG_DRIVER_AT91EMAC_QUIET -#define VERBOSEP(...) printf(__VA_ARGS__); +#define VERBOSEP 1 #else -#define VERBOSEP(...) +#define VERBOSEP 0 #endif #define RBF_ADDR 0xfffffffc @@ -93,7 +68,7 @@ #define RBF_MULTICAST (1<<30) #define RBF_UNICAST (1<<29) #define RBF_EXTERNAL (1<<28) -#define RBF_UNKOWN (1<<27) +#define RBF_UNKNOWN (1<<27) #define RBF_SIZE 0x07ff #define RBF_LOCAL4 (1<<26) #define RBF_LOCAL3 (1<<25) @@ -127,18 +102,25 @@ 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_cond(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); - DEBUG_AT91PHY("AT91PHY read %x REG(%d)=%x\n", at91mac, reg, *value) + debug_cond(DEBUG_AT91PHY, + "AT91PHY read %p REG(%d)=%x\n", at91mac, reg, *value); return 0; } @@ -146,7 +128,9 @@ 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) { - DEBUG_AT91PHY("AT91PHY write %x REG(%d)=%x\n", at91mac, reg, &value) + unsigned long netstat; + debug_cond(DEBUG_AT91PHY, + "AT91PHY write %p REG(%d)=%p\n", at91mac, reg, &value); at91emac_EnableMDIO(at91mac); @@ -154,15 +138,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_cond(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; @@ -170,23 +159,23 @@ at91_emac_t *get_emacbase_by_name(char *devname) return (at91_emac_t *) netdev->iobase; } -int at91emac_mii_read(char *devname, unsigned char addr, - unsigned char reg, unsigned short *value) +int at91emac_mii_read(struct mii_dev *bus, int addr, int devad, int reg) { + unsigned short value = 0; at91_emac_t *emac; - emac = get_emacbase_by_name(devname); - at91emac_read(emac , addr, reg, value); - return 0; + emac = get_emacbase_by_name(bus->name); + at91emac_read(emac , addr, reg, &value); + return value; } -int at91emac_mii_write(char *devname, unsigned char addr, - unsigned char reg, unsigned short value) +int at91emac_mii_write(struct mii_dev *bus, int addr, int devad, int reg, + u16 value) { at91_emac_t *emac; - emac = get_emacbase_by_name(devname); + emac = get_emacbase_by_name(bus->name); at91emac_write(emac, addr, reg, value); return 0; } @@ -204,11 +193,11 @@ static int at91emac_phy_reset(struct eth_device *netdev) adv = ADVERTISE_CSMA | ADVERTISE_ALL; at91emac_write(emac, CONFIG_DRIVER_AT91EMAC_PHYADDR, MII_ADVERTISE, adv); - VERBOSEP("%s: Starting autonegotiation...\n", netdev->name); + debug_cond(VERBOSEP, "%s: Starting autonegotiation...\n", netdev->name); at91emac_write(emac, CONFIG_DRIVER_AT91EMAC_PHYADDR, MII_BMCR, (BMCR_ANENABLE | BMCR_ANRESTART)); - for (i = 0; i < 100000 / 100; i++) { + for (i = 0; i < 30000; i++) { at91emac_read(emac, CONFIG_DRIVER_AT91EMAC_PHYADDR, MII_BMSR, &status); if (status & BMSR_ANEGCOMPLETE) @@ -217,11 +206,12 @@ static int at91emac_phy_reset(struct eth_device *netdev) } if (status & BMSR_ANEGCOMPLETE) { - VERBOSEP("%s: Autonegotiation complete\n", netdev->name); + debug_cond(VERBOSEP, + "%s: Autonegotiation complete\n", netdev->name); } else { printf("%s: Autonegotiation timed out (status=0x%04x)\n", netdev->name, status); - return 1; + return -1; } return 0; } @@ -240,7 +230,7 @@ static int at91emac_phy_init(struct eth_device *netdev) MII_PHYSID1, &phy_id); if (phy_id == 0xffff) { printf("%s: No PHY present\n", netdev->name); - return 1; + return -1; } at91emac_read(emac, CONFIG_DRIVER_AT91EMAC_PHYADDR, @@ -249,7 +239,7 @@ static int at91emac_phy_init(struct eth_device *netdev) 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, CONFIG_DRIVER_AT91EMAC_PHYADDR, @@ -260,8 +250,8 @@ static int at91emac_phy_init(struct eth_device *netdev) } } if (!(status & BMSR_LSTATUS)) { - VERBOSEP("%s: link down\n", netdev->name); - return 3; + debug_cond(VERBOSEP, "%s: link down\n", netdev->name); + return -3; } else { at91emac_read(emac, CONFIG_DRIVER_AT91EMAC_PHYADDR, MII_ADVERTISE, &adv); @@ -271,7 +261,7 @@ static int at91emac_phy_init(struct eth_device *netdev) speed = (media & (ADVERTISE_100FULL | ADVERTISE_100HALF) ? 1 : 0); duplex = (media & ADVERTISE_FULL) ? 1 : 0; - VERBOSEP("%s: link up, %sMbps %s-duplex\n", + debug_cond(VERBOSEP, "%s: link up, %sMbps %s-duplex\n", netdev->name, speed ? "100" : "10", duplex ? "full" : "half"); @@ -286,7 +276,7 @@ int at91emac_UpdateLinkSpeed(at91_emac_t *emac) 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 */ @@ -321,7 +311,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) @@ -330,39 +320,39 @@ static int at91emac_init(struct eth_device *netdev, bd_t *bd) u32 value; emac_device *dev; at91_emac_t *emac; - at91_pio_t *pio = (at91_pio_t *) AT91_PIO_BASE; - at91_pmc_t *pmc = (at91_pmc_t *) AT91_PMC_BASE; + at91_pio_t *pio = (at91_pio_t *) ATMEL_BASE_PIO; emac = (at91_emac_t *) netdev->iobase; dev = (emac_device *) netdev->priv; /* PIO Disable Register */ - value = AT91_PMX_AA_EMDIO | AT91_PMX_AA_EMDC | - AT91_PMX_AA_ERXER | AT91_PMX_AA_ERX1 | - AT91_PMX_AA_ERX0 | AT91_PMX_AA_ECRS | - AT91_PMX_AA_ETX1 | AT91_PMX_AA_ETX0 | - AT91_PMX_AA_ETXEN | AT91_PMX_AA_EREFCK; + value = ATMEL_PMX_AA_EMDIO | ATMEL_PMX_AA_EMDC | + ATMEL_PMX_AA_ERXER | ATMEL_PMX_AA_ERX1 | + ATMEL_PMX_AA_ERX0 | ATMEL_PMX_AA_ECRS | + ATMEL_PMX_AA_ETX1 | ATMEL_PMX_AA_ETX0 | + ATMEL_PMX_AA_ETXEN | ATMEL_PMX_AA_EREFCK; writel(value, &pio->pioa.pdr); writel(value, &pio->pioa.asr); #ifdef CONFIG_RMII - value = AT91_PMX_BA_ERXCK; + value = ATMEL_PMX_BA_ERXCK; #else - value = AT91_PMX_BA_ERXCK | AT91_PMX_BA_ECOL | - AT91_PMX_BA_ERXDV | AT91_PMX_BA_ERX3 | - AT91_PMX_BA_ERX2 | AT91_PMX_BA_ETXER | - AT91_PMX_BA_ETX3 | AT91_PMX_BA_ETX2; + value = ATMEL_PMX_BA_ERXCK | ATMEL_PMX_BA_ECOL | + ATMEL_PMX_BA_ERXDV | ATMEL_PMX_BA_ERX3 | + ATMEL_PMX_BA_ERX2 | ATMEL_PMX_BA_ETXER | + ATMEL_PMX_BA_ETX3 | ATMEL_PMX_BA_ETX2; #endif writel(value, &pio->piob.pdr); writel(value, &pio->piob.bsr); - writel(1 << AT91_ID_EMAC, &pmc->pcer); + at91_periph_clk_enable(ATMEL_ID_EMAC); + writel(readl(&emac->ctl) | AT91_EMAC_CTL_CSR, &emac->ctl); /* Init Ethernet buffers */ for (i = 0; i < RBF_FRAMEMAX; i++) { - dev->rbfdt[i].addr = (unsigned long) NetRxPackets[i]; + dev->rbfdt[i].addr = (unsigned long) net_rx_packets[i]; dev->rbfdt[i].size = 0; } dev->rbfdt[RBF_FRAMEMAX - 1].addr |= RBF_WRAP; @@ -387,7 +377,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) @@ -397,11 +387,10 @@ static void at91emac_halt(struct eth_device *netdev) emac = (at91_emac_t *) netdev->iobase; writel(readl(&emac->ctl) & ~(AT91_EMAC_CTL_TE | AT91_EMAC_CTL_RE), &emac->ctl); - DEBUG_AT91EMAC("halt MAC\n"); + debug_cond(DEBUG_AT91EMAC, "halt MAC\n"); } -static int at91emac_send(struct eth_device *netdev, volatile void *packet, - int length) +static int at91emac_send(struct eth_device *netdev, void *packet, int length) { at91_emac_t *emac; @@ -413,7 +402,7 @@ static int at91emac_send(struct eth_device *netdev, volatile void *packet, writel(AT91_EMAC_TCR_LEN(length), &emac->tcr); while (AT91_EMAC_TCR_LEN(readl(&emac->tcr))) ; - DEBUG_AT91EMAC("Send %d \n", length); + debug_cond(DEBUG_AT91EMAC, "Send %d\n", length); writel(readl(&emac->tsr) | AT91_EMAC_TSR_COMP, &emac->tsr); return 0; } @@ -431,9 +420,9 @@ static int at91emac_recv(struct eth_device *netdev) rbfp = &dev->rbfdt[dev->rbindex]; while (rbfp->addr & RBF_OWNER) { size = rbfp->size & RBF_SIZE; - NetReceive(NetRxPackets[dev->rbindex], size); + net_process_received_packet(net_rx_packets[dev->rbindex], size); - DEBUG_AT91EMAC("Recv[%d]: %d bytes @ %x \n", + debug_cond(DEBUG_AT91EMAC, "Recv[%ld]: %d bytes @ %lx\n", dev->rbindex, size, rbfp->addr); rbfp->addr &= ~RBF_OWNER; @@ -462,19 +451,20 @@ static int at91emac_recv(struct eth_device *netdev) 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", + at91_periph_clk_enable(ATMEL_ID_EMAC); + + debug_cond(DEBUG_AT91EMAC, + "init MAC-ADDR %02x:%02x:%02x:%02x:%02x:%02x\n", + netdev->enetaddr[5], netdev->enetaddr[4], netdev->enetaddr[3], + netdev->enetaddr[2], netdev->enetaddr[1], netdev->enetaddr[0]); + writel( (netdev->enetaddr[0] | netdev->enetaddr[1] << 8 | + netdev->enetaddr[2] << 16 | netdev->enetaddr[3] << 24), + &emac->sa2l); + writel((netdev->enetaddr[4] | netdev->enetaddr[5] << 8), &emac->sa2h); + debug_cond(DEBUG_AT91EMAC, "init MAC-ADDR %x%x\n", readl(&emac->sa2h), readl(&emac->sa2l)); return 0; } @@ -486,25 +476,21 @@ int at91emac_register(bd_t *bis, unsigned long iobase) struct eth_device *dev; if (iobase == 0) - iobase = AT91_EMAC_BASE; + iobase = ATMEL_BASE_EMAC; 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 + strcpy(dev->name, "emac"); dev->iobase = iobase; dev->priv = emacfix; dev->init = at91emac_init; @@ -516,7 +502,17 @@ int at91emac_register(bd_t *bis, unsigned long iobase) eth_register(dev); #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) - miiphy_register(dev->name, at91emac_mii_read, at91emac_mii_write); + int retval; + struct mii_dev *mdiodev = mdio_alloc(); + if (!mdiodev) + return -ENOMEM; + strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN); + mdiodev->read = at91emac_mii_read; + mdiodev->write = at91emac_mii_write; + + retval = mdio_register(mdiodev); + if (retval < 0) + return retval; #endif return 1; }