X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fmcffec.c;h=8caf0ba6b1ca3b3dbbabff2b6de37901aa5e50f8;hb=29a4a9f1056fd4cc319c248c2e062cd91f6fa9f2;hp=5ab4726ff584ad6609e016ebedd0b6664d1432fa;hpb=10a3367955bc2033b288915f8f10d0e507fe2fa1;p=oweals%2Fu-boot.git diff --git a/drivers/net/mcffec.c b/drivers/net/mcffec.c index 5ab4726ff5..8caf0ba6b1 100644 --- a/drivers/net/mcffec.c +++ b/drivers/net/mcffec.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * (C) Copyright 2000-2004 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. @@ -5,36 +6,20 @@ * (C) Copyright 2007 Freescale Semiconductor, Inc. * TsiChung Liew (Tsi-Chung.Liew@freescale.com) * - * 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 + * Conversion to DM + * (C) 2019 Angelo Dureghello */ #include +#include +#include #include - -#ifdef CONFIG_MCFFEC - -#include -#include - #include #include #include +#include +#include +#include #undef ET_DEBUG #undef MII_DEBUG @@ -43,7 +28,6 @@ #define DBUF_LENGTH 1520 #define TX_BUF_CNT 2 #define PKT_MAXBUF_SIZE 1518 -#define PKT_MINBUF_SIZE 64 #define PKT_MAXBLR_SIZE 1520 #define LAST_PKTBUFSRX PKTBUFSRX - 1 #define BD_ENET_RX_W_E (BD_ENET_RX_WRAP | BD_ENET_RX_EMPTY) @@ -51,67 +35,61 @@ DECLARE_GLOBAL_DATA_PTR; -#if defined(CONFIG_CMD_NET) && defined(CONFIG_NET_MULTI) - -struct fec_info_s fec_info[] = { -#ifdef CFG_FEC0_IOBASE - { - 0, /* index */ - CFG_FEC0_IOBASE, /* io base */ - CFG_FEC0_PINMUX, /* gpio pin muxing */ - CFG_FEC0_MIIBASE, /* mii base */ - -1, /* phy_addr */ - 0, /* duplex and speed */ - 0, /* phy name */ - 0, /* phyname init */ - 0, /* RX BD */ - 0, /* TX BD */ - 0, /* rx Index */ - 0, /* tx Index */ - 0, /* tx buffer */ - 0, /* initialized flag */ - }, -#endif -#ifdef CFG_FEC1_IOBASE - { - 1, /* index */ - CFG_FEC1_IOBASE, /* io base */ - CFG_FEC1_PINMUX, /* gpio pin muxing */ - CFG_FEC1_MIIBASE, /* mii base */ - -1, /* phy_addr */ - 0, /* duplex and speed */ - 0, /* phy name */ - 0, /* phy name init */ - 0, /* RX BD */ - 0, /* TX BD */ - 0, /* rx Index */ - 0, /* tx Index */ - 0, /* tx buffer */ - 0, /* initialized flag */ - } +static void init_eth_info(struct fec_info_s *info) +{ +#ifdef CONFIG_SYS_FEC_BUF_USE_SRAM + static u32 tmp; + + if (info->index == 0) + tmp = CONFIG_SYS_INIT_RAM_ADDR + 0x1000; + else + info->rxbd = (cbd_t *)DBUF_LENGTH; + + /* setup Receive and Transmit buffer descriptor */ + info->rxbd = (cbd_t *)((u32)info->rxbd + tmp); + tmp = (u32)info->rxbd; + info->txbd = + (cbd_t *)((u32)info->txbd + tmp + + (PKTBUFSRX * sizeof(cbd_t))); + tmp = (u32)info->txbd; + info->txbuf = + (char *)((u32)info->txbuf + tmp + + (CONFIG_SYS_TX_ETH_BUFFER * sizeof(cbd_t))); + tmp = (u32)info->txbuf; +#else + info->rxbd = + (cbd_t *)memalign(CONFIG_SYS_CACHELINE_SIZE, + (PKTBUFSRX * sizeof(cbd_t))); + info->txbd = + (cbd_t *)memalign(CONFIG_SYS_CACHELINE_SIZE, + (TX_BUF_CNT * sizeof(cbd_t))); + info->txbuf = + (char *)memalign(CONFIG_SYS_CACHELINE_SIZE, DBUF_LENGTH); #endif -}; -int fec_send(struct eth_device *dev, volatile void *packet, int length); -int fec_recv(struct eth_device *dev); -int fec_init(struct eth_device *dev, bd_t * bd); -void fec_halt(struct eth_device *dev); -void fec_reset(struct eth_device *dev); - -extern int fecpin_setclear(struct eth_device *dev, int setclear); - -#ifdef CFG_DISCOVER_PHY -extern void __mii_init(void); -extern uint mii_send(uint mii_cmd); -extern int mii_discover_phy(struct eth_device *dev); -extern int mcffec_miiphy_read(char *devname, unsigned char addr, - unsigned char reg, unsigned short *value); -extern int mcffec_miiphy_write(char *devname, unsigned char addr, - unsigned char reg, unsigned short value); +#ifdef ET_DEBUG + printf("rxbd %x txbd %x\n", (int)info->rxbd, (int)info->txbd); #endif + info->phy_name = (char *)memalign(CONFIG_SYS_CACHELINE_SIZE, 32); +} -void setFecDuplexSpeed(volatile fec_t * fecp, bd_t * bd, int dup_spd) +static void fec_reset(struct fec_info_s *info) { + volatile fec_t *fecp = (fec_t *)(info->iobase); + int i; + + fecp->ecr = FEC_ECR_RESET; + for (i = 0; (fecp->ecr & FEC_ECR_RESET) && (i < FEC_RESET_DELAY); ++i) + udelay(1); + + if (i == FEC_RESET_DELAY) + printf("FEC_RESET_DELAY timeout\n"); +} + +static void set_fec_duplex_speed(volatile fec_t *fecp, int dup_spd) +{ + bd_t *bd = gd->bd; + if ((dup_spd >> 16) == FULL) { /* Set maximum frame length */ fecp->rcr = FEC_RCR_MAX_FL(PKT_MAXBUF_SIZE) | FEC_RCR_MII_MODE | @@ -125,11 +103,17 @@ void setFecDuplexSpeed(volatile fec_t * fecp, bd_t * bd, int dup_spd) } if ((dup_spd & 0xFFFF) == _100BASET) { +#ifdef CONFIG_MCF5445x + fecp->rcr &= ~0x200; /* disabled 10T base */ +#endif #ifdef MII_DEBUG printf("100Mbps\n"); #endif bd->bi_ethspeed = 100; } else { +#ifdef CONFIG_MCF5445x + fecp->rcr |= 0x200; /* enabled 10T base */ +#endif #ifdef MII_DEBUG printf("10Mbps\n"); #endif @@ -137,129 +121,11 @@ void setFecDuplexSpeed(volatile fec_t * fecp, bd_t * bd, int dup_spd) } } -int fec_send(struct eth_device *dev, volatile void *packet, int length) -{ - struct fec_info_s *info = dev->priv; - volatile fec_t *fecp = (fec_t *) (info->iobase); - int j, rc; - u16 phyStatus; - - miiphy_read(dev->name, info->phy_addr, PHY_BMSR, &phyStatus); - - /* section 16.9.23.3 - * Wait for ready - */ - j = 0; - while ((info->txbd[info->txIdx].cbd_sc & BD_ENET_TX_READY) && - (j < MCFFEC_TOUT_LOOP)) { - udelay(1); - j++; - } - if (j >= MCFFEC_TOUT_LOOP) { - printf("TX not ready\n"); - } - - info->txbd[info->txIdx].cbd_bufaddr = (uint) packet; - info->txbd[info->txIdx].cbd_datlen = length; - info->txbd[info->txIdx].cbd_sc |= BD_ENET_TX_RDY_LST; - - /* Activate transmit Buffer Descriptor polling */ - fecp->tdar = 0x01000000; /* Descriptor polling active */ - - /* FEC fix for MCF5275, FEC unable to initial transmit data packet. - * A nop will ensure the descriptor polling active completed. - */ -#ifdef CONFIG_M5275 - __asm__ ("nop"); -#endif - -#ifdef CFG_UNIFY_CACHE - icache_invalid(); -#endif - j = 0; - while ((info->txbd[info->txIdx].cbd_sc & BD_ENET_TX_READY) && - (j < MCFFEC_TOUT_LOOP)) { - udelay(1); - j++; - } - if (j >= MCFFEC_TOUT_LOOP) { - printf("TX timeout\n"); - } - -#ifdef ET_DEBUG - printf("%s[%d] %s: cycles: %d status: %x retry cnt: %d\n", - __FILE__, __LINE__, __FUNCTION__, j, - info->txbd[info->txIdx].cbd_sc, - (info->txbd[info->txIdx].cbd_sc & 0x003C) >> 2); -#endif - - /* return only status bits */ - rc = (info->txbd[info->txIdx].cbd_sc & BD_ENET_TX_STATS); - info->txIdx = (info->txIdx + 1) % TX_BUF_CNT; - - return rc; -} - -int fec_recv(struct eth_device *dev) -{ - struct fec_info_s *info = dev->priv; - volatile fec_t *fecp = (fec_t *) (info->iobase); - int length; - - for (;;) { -#ifdef CFG_UNIFY_CACHE - icache_invalid(); -#endif - /* section 16.9.23.2 */ - if (info->rxbd[info->rxIdx].cbd_sc & BD_ENET_RX_EMPTY) { - length = -1; - break; /* nothing received - leave for() loop */ - } - - length = info->rxbd[info->rxIdx].cbd_datlen; - - if (info->rxbd[info->rxIdx].cbd_sc & 0x003f) { - printf("%s[%d] err: %x\n", - __FUNCTION__, __LINE__, - info->rxbd[info->rxIdx].cbd_sc); -#ifdef ET_DEBUG - printf("%s[%d] err: %x\n", - __FUNCTION__, __LINE__, - info->rxbd[info->rxIdx].cbd_sc); -#endif - } else { - - length -= 4; - /* Pass the packet up to the protocol layers. */ - NetReceive(NetRxPackets[info->rxIdx], length); - - fecp->eir |= FEC_EIR_RXF; - } - - /* Give the buffer back to the FEC. */ - info->rxbd[info->rxIdx].cbd_datlen = 0; - - /* wrap around buffer index when necessary */ - if (info->rxIdx == LAST_PKTBUFSRX) { - info->rxbd[PKTBUFSRX - 1].cbd_sc = BD_ENET_RX_W_E; - info->rxIdx = 0; - } else { - info->rxbd[info->rxIdx].cbd_sc = BD_ENET_RX_EMPTY; - info->rxIdx++; - } - - /* Try to fill Buffer Descriptors */ - fecp->rdar = 0x01000000; /* Descriptor polling active */ - } - - return length; -} - #ifdef ET_DEBUG -void dbgFecRegs(struct eth_device *dev) +static void dbg_fec_regs(struct udevice *dev) { struct fec_info_s *info = dev->priv; - volatile fec_t *fecp = (fec_t *) (info->iobase); + volatile fec_t *fecp = (fec_t *)(info->iobase); printf("=====\n"); printf("ievent %x - %x\n", (int)&fecp->eir, fecp->eir); @@ -406,28 +272,27 @@ void dbgFecRegs(struct eth_device *dev) } #endif -int fec_init(struct eth_device *dev, bd_t * bd) +int mcffec_init(struct udevice *dev) { struct fec_info_s *info = dev->priv; volatile fec_t *fecp = (fec_t *) (info->iobase); - int i; - u8 *ea = NULL; - - fecpin_setclear(dev, 1); + int rval, i; + uchar ea[6]; - fec_reset(dev); + fecpin_setclear(info, 1); + fec_reset(info); #if defined(CONFIG_CMD_MII) || defined (CONFIG_MII) || \ - defined (CFG_DISCOVER_PHY) + defined (CONFIG_SYS_DISCOVER_PHY) mii_init(); - setFecDuplexSpeed(fecp, bd, info->dup_spd); + set_fec_duplex_speed(fecp, info->dup_spd); #else -#ifndef CFG_DISCOVER_PHY - setFecDuplexSpeed(fecp, bd, (FECDUPLEX << 16) | FECSPEED); -#endif /* ifndef CFG_DISCOVER_PHY */ -#endif /* CONFIG_CMD_MII || CONFIG_MII */ +#ifndef CONFIG_SYS_DISCOVER_PHY + set_fec_duplex_speed(fecp, (FECDUPLEX << 16) | FECSPEED); +#endif /* ifndef CONFIG_SYS_DISCOVER_PHY */ +#endif /* CONFIG_CMD_MII || CONFIG_MII */ /* We use strictly polling mode only */ fecp->eimr = 0; @@ -436,34 +301,20 @@ int fec_init(struct eth_device *dev, bd_t * bd) fecp->eir = 0xffffffff; /* Set station address */ - if ((u32) fecp == CFG_FEC0_IOBASE) { -#ifdef CFG_FEC1_IOBASE - volatile fec_t *fecp1 = (fec_t *) (CFG_FEC1_IOBASE); - ea = &bd->bi_enet1addr[0]; - fecp1->palr = - (ea[0] << 24) | (ea[1] << 16) | (ea[2] << 8) | (ea[3]); - fecp1->paur = (ea[4] << 24) | (ea[5] << 16); -#endif - ea = &bd->bi_enetaddr[0]; - fecp->palr = - (ea[0] << 24) | (ea[1] << 16) | (ea[2] << 8) | (ea[3]); - fecp->paur = (ea[4] << 24) | (ea[5] << 16); - } else { -#ifdef CFG_FEC0_IOBASE - volatile fec_t *fecp0 = (fec_t *) (CFG_FEC0_IOBASE); - ea = &bd->bi_enetaddr[0]; - fecp0->palr = - (ea[0] << 24) | (ea[1] << 16) | (ea[2] << 8) | (ea[3]); - fecp0->paur = (ea[4] << 24) | (ea[5] << 16); -#endif -#ifdef CFG_FEC1_IOBASE - ea = &bd->bi_enet1addr[0]; - fecp->palr = - (ea[0] << 24) | (ea[1] << 16) | (ea[2] << 8) | (ea[3]); - fecp->paur = (ea[4] << 24) | (ea[5] << 16); -#endif + if (info->index == 0) + rval = eth_env_get_enetaddr("ethaddr", ea); + else + rval = eth_env_get_enetaddr("eth1addr", ea); + + if (!rval) { + puts("Please set a valid MAC address\n"); + return -EINVAL; } + fecp->palr = + (ea[0] << 24) | (ea[1] << 16) | (ea[2] << 8) | (ea[3]); + fecp->paur = (ea[4] << 24) | (ea[5] << 16); + /* Clear unicast address hash table */ fecp->iaur = 0; fecp->ialr = 0; @@ -476,10 +327,10 @@ int fec_init(struct eth_device *dev, bd_t * bd) fecp->emrbr = PKT_MAXBLR_SIZE; /* - * Setup Buffers and Buffer Desriptors + * Setup Buffers and Buffer Descriptors */ - info->rxIdx = 0; - info->txIdx = 0; + info->rx_idx = 0; + info->tx_idx = 0; /* * Setup Receiver Buffer Descriptors (13.14.24.18) @@ -489,7 +340,7 @@ int fec_init(struct eth_device *dev, bd_t * bd) for (i = 0; i < PKTBUFSRX; i++) { info->rxbd[i].cbd_sc = BD_ENET_RX_EMPTY; info->rxbd[i].cbd_datlen = 0; /* Reset */ - info->rxbd[i].cbd_bufaddr = (uint) NetRxPackets[i]; + info->rxbd[i].cbd_bufaddr = (uint) net_rx_packets[i]; } info->rxbd[PKTBUFSRX - 1].cbd_sc |= BD_ENET_RX_WRAP; @@ -512,93 +363,256 @@ int fec_init(struct eth_device *dev, bd_t * bd) /* Now enable the transmit and receive processing */ fecp->ecr |= FEC_ECR_ETHER_EN; - /* And last, try to fill Rx Buffer Descriptors */ - fecp->rdar = 0x01000000; /* Descriptor polling active */ + /* And last, try to fill Rx Buffer Descriptors + * Descriptor polling active + */ + fecp->rdar = 0x01000000; - return 1; + return 0; } -void fec_reset(struct eth_device *dev) +static int mcffec_send(struct udevice *dev, void *packet, int length) { struct fec_info_s *info = dev->priv; - volatile fec_t *fecp = (fec_t *) (info->iobase); - int i; + volatile fec_t *fecp = (fec_t *)info->iobase; + int j, rc; + u16 phy_status; - fecp->ecr = FEC_ECR_RESET; - for (i = 0; (fecp->ecr & FEC_ECR_RESET) && (i < FEC_RESET_DELAY); ++i) { + miiphy_read(dev->name, info->phy_addr, MII_BMSR, &phy_status); + + /* section 16.9.23.3 + * Wait for ready + */ + j = 0; + while ((info->txbd[info->tx_idx].cbd_sc & BD_ENET_TX_READY) && + (j < info->to_loop)) { udelay(1); + j++; } - if (i == FEC_RESET_DELAY) { - printf("FEC_RESET_DELAY timeout\n"); + if (j >= info->to_loop) + printf("TX not ready\n"); + + info->txbd[info->tx_idx].cbd_bufaddr = (uint)packet; + info->txbd[info->tx_idx].cbd_datlen = length; + info->txbd[info->tx_idx].cbd_sc |= BD_ENET_TX_RDY_LST; + + /* Activate transmit Buffer Descriptor polling */ + fecp->tdar = 0x01000000; /* Descriptor polling active */ + +#ifndef CONFIG_SYS_FEC_BUF_USE_SRAM + /* + * FEC unable to initial transmit data packet. + * A nop will ensure the descriptor polling active completed. + * CF Internal RAM has shorter cycle access than DRAM. If use + * DRAM as Buffer descriptor and data, a nop is a must. + * Affect only V2 and V3. + */ + __asm__ ("nop"); +#endif + +#ifdef CONFIG_SYS_UNIFY_CACHE + icache_invalid(); +#endif + + j = 0; + while ((info->txbd[info->tx_idx].cbd_sc & BD_ENET_TX_READY) && + (j < info->to_loop)) { + udelay(1); + j++; + } + if (j >= info->to_loop) + printf("TX timeout\n"); + +#ifdef ET_DEBUG + printf("%s[%d] %s: cycles: %d status: %x retry cnt: %d\n", + __FILE__, __LINE__, __func__, j, + info->txbd[info->tx_idx].cbd_sc, + (info->txbd[info->tx_idx].cbd_sc & 0x003C) >> 2); +#endif + + /* return only status bits */ + rc = (info->txbd[info->tx_idx].cbd_sc & BD_ENET_TX_STATS); + info->tx_idx = (info->tx_idx + 1) % TX_BUF_CNT; + + return rc; +} + +static int mcffec_recv(struct udevice *dev, int flags, uchar **packetp) +{ + struct fec_info_s *info = dev->priv; + volatile fec_t *fecp = (fec_t *)info->iobase; + int length = -1; + + for (;;) { +#ifdef CONFIG_SYS_UNIFY_CACHE + icache_invalid(); +#endif + /* If nothing received - leave for() loop */ + if (info->rxbd[info->rx_idx].cbd_sc & BD_ENET_RX_EMPTY) + break; + + length = info->rxbd[info->rx_idx].cbd_datlen; + + if (info->rxbd[info->rx_idx].cbd_sc & 0x003f) { + printf("%s[%d] err: %x\n", + __func__, __LINE__, + info->rxbd[info->rx_idx].cbd_sc); + } else { + length -= 4; + + /* + * Pass the buffer ptr up to the protocol layers. + */ + *packetp = net_rx_packets[info->rx_idx]; + + fecp->eir |= FEC_EIR_RXF; + } + + /* Give the buffer back to the FEC. */ + info->rxbd[info->rx_idx].cbd_datlen = 0; + + /* wrap around buffer index when necessary */ + if (info->rx_idx == LAST_PKTBUFSRX) { + info->rxbd[PKTBUFSRX - 1].cbd_sc = BD_ENET_RX_W_E; + info->rx_idx = 0; + } else { + info->rxbd[info->rx_idx].cbd_sc = BD_ENET_RX_EMPTY; + info->rx_idx++; + } + + /* Try to fill Buffer Descriptors + * Descriptor polling active + */ + fecp->rdar = 0x01000000; } + + return length; } -void fec_halt(struct eth_device *dev) +static void mcffec_halt(struct udevice *dev) { struct fec_info_s *info = dev->priv; - fec_reset(dev); + fec_reset(info); + fecpin_setclear(info, 0); - fecpin_setclear(dev, 0); + info->rx_idx = 0; + info->tx_idx = 0; - info->rxIdx = info->txIdx = 0; memset(info->rxbd, 0, PKTBUFSRX * sizeof(cbd_t)); memset(info->txbd, 0, TX_BUF_CNT * sizeof(cbd_t)); memset(info->txbuf, 0, DBUF_LENGTH); } -int mcffec_initialize(bd_t * bis) +static const struct eth_ops mcffec_ops = { + .start = mcffec_init, + .send = mcffec_send, + .recv = mcffec_recv, + .stop = mcffec_halt, +}; + +/* + * Boot sequence, called just after mcffec_ofdata_to_platdata, + * as DM way, it replaces old mcffec_initialize. + */ +static int mcffec_probe(struct udevice *dev) { - struct eth_device *dev; - int i; + struct eth_pdata *pdata = dev_get_platdata(dev); + struct fec_info_s *info = dev->priv; + int node = dev_of_offset(dev); + int retval, fec_idx; + const u32 *val; - for (i = 0; i < sizeof(fec_info) / sizeof(fec_info[0]); i++) { - - dev = - (struct eth_device *)memalign(CFG_CACHELINE_SIZE, - sizeof *dev); - if (dev == NULL) - hang(); - - memset(dev, 0, sizeof(*dev)); - - sprintf(dev->name, "FEC%d", fec_info[i].index); - - dev->priv = &fec_info[i]; - dev->init = fec_init; - dev->halt = fec_halt; - dev->send = fec_send; - dev->recv = fec_recv; - - /* setup Receive and Transmit buffer descriptor */ - fec_info[i].rxbd = - (cbd_t *) memalign(CFG_CACHELINE_SIZE, - (PKTBUFSRX * sizeof(cbd_t))); - fec_info[i].txbd = - (cbd_t *) memalign(CFG_CACHELINE_SIZE, - (TX_BUF_CNT * sizeof(cbd_t))); - fec_info[i].txbuf = - (char *)memalign(CFG_CACHELINE_SIZE, DBUF_LENGTH); -#ifdef ET_DEBUG - printf("rxbd %x txbd %x\n", - (int)fec_info[i].rxbd, (int)fec_info[i].txbd); -#endif + info->index = dev->seq; + info->iobase = pdata->iobase; + info->phy_addr = -1; - fec_info[i].phy_name = (char *)memalign(CFG_CACHELINE_SIZE, 32); + val = fdt_getprop(gd->fdt_blob, node, "mii-base", NULL); + if (val) { + u32 fec_iobase; - eth_register(dev); + fec_idx = fdt32_to_cpu(*val); + if (fec_idx == info->index) { + fec_iobase = info->iobase; + } else { + printf("mii base != base address, fec_idx %d\n", + fec_idx); + retval = fec_get_base_addr(fec_idx, &fec_iobase); + if (retval) + return retval; + } + info->miibase = fec_iobase; + } + + val = fdt_getprop(gd->fdt_blob, node, "phy-addr", NULL); + if (val) + info->phy_addr = fdt32_to_cpu(*val); + + val = fdt_getprop(gd->fdt_blob, node, "timeout-loop", NULL); + if (val) + info->to_loop = fdt32_to_cpu(*val); + + init_eth_info(info); #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) - miiphy_register(dev->name, - mcffec_miiphy_read, mcffec_miiphy_write); + info->bus = mdio_alloc(); + if (!info->bus) + return -ENOMEM; + strcpy(info->bus->name, dev->name); + info->bus->read = mcffec_miiphy_read; + info->bus->write = mcffec_miiphy_write; + + retval = mdio_register(info->bus); + if (retval < 0) + return retval; #endif - } - /* default speed */ - bis->bi_ethspeed = 10; + return 0; +} + +static int mcffec_remove(struct udevice *dev) +{ + struct fec_info_s *priv = dev_get_priv(dev); + + mdio_unregister(priv->bus); + mdio_free(priv->bus); - return 1; + return 0; } -#endif /* CONFIG_CMD_NET, FEC_ENET & NET_MULTI */ -#endif /* CONFIG_MCFFEC */ +/* + * Boot sequence, called 1st + */ +static int mcffec_ofdata_to_platdata(struct udevice *dev) +{ + struct eth_pdata *pdata = dev_get_platdata(dev); + const u32 *val; + + pdata->iobase = (phys_addr_t)devfdt_get_addr(dev); + /* Default to 10Mbit/s */ + pdata->max_speed = 10; + + val = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), + "max-speed", NULL); + if (val) + pdata->max_speed = fdt32_to_cpu(*val); + + return 0; +} + +static const struct udevice_id mcffec_ids[] = { + { .compatible = "fsl,mcf-fec" }, + { } +}; + +U_BOOT_DRIVER(mcffec) = { + .name = "mcffec", + .id = UCLASS_ETH, + .of_match = mcffec_ids, + .ofdata_to_platdata = mcffec_ofdata_to_platdata, + .probe = mcffec_probe, + .remove = mcffec_remove, + .ops = &mcffec_ops, + .priv_auto_alloc_size = sizeof(struct fec_info_s), + .platdata_auto_alloc_size = sizeof(struct eth_pdata), +};