+static void fec_set_dev_name(char *dest, int dev_id)
+{
+ sprintf(dest, (dev_id == -1) ? "FEC" : "FEC%i", dev_id);
+}
+
+static int fec_alloc_descs(struct fec_priv *fec)
+{
+ unsigned int size;
+ int i;
+ uint8_t *data;
+
+ /* Allocate TX descriptors. */
+ size = roundup(2 * sizeof(struct fec_bd), ARCH_DMA_MINALIGN);
+ fec->tbd_base = memalign(ARCH_DMA_MINALIGN, size);
+ if (!fec->tbd_base)
+ goto err_tx;
+
+ /* Allocate RX descriptors. */
+ size = roundup(FEC_RBD_NUM * sizeof(struct fec_bd), ARCH_DMA_MINALIGN);
+ fec->rbd_base = memalign(ARCH_DMA_MINALIGN, size);
+ if (!fec->rbd_base)
+ goto err_rx;
+
+ memset(fec->rbd_base, 0, size);
+
+ /* Allocate RX buffers. */
+
+ /* Maximum RX buffer size. */
+ size = roundup(FEC_MAX_PKT_SIZE, FEC_DMA_RX_MINALIGN);
+ for (i = 0; i < FEC_RBD_NUM; i++) {
+ data = memalign(FEC_DMA_RX_MINALIGN, size);
+ if (!data) {
+ printf("%s: error allocating rxbuf %d\n", __func__, i);
+ goto err_ring;
+ }
+
+ memset(data, 0, size);
+
+ fec->rbd_base[i].data_pointer = (uint32_t)data;
+ fec->rbd_base[i].status = FEC_RBD_EMPTY;
+ fec->rbd_base[i].data_length = 0;
+ /* Flush the buffer to memory. */
+ flush_dcache_range((uint32_t)data, (uint32_t)data + size);
+ }
+
+ /* Mark the last RBD to close the ring. */
+ fec->rbd_base[i - 1].status = FEC_RBD_WRAP | FEC_RBD_EMPTY;
+
+ fec->rbd_index = 0;
+ fec->tbd_index = 0;
+
+ return 0;
+
+err_ring:
+ for (; i >= 0; i--)
+ free((void *)fec->rbd_base[i].data_pointer);
+ free(fec->rbd_base);
+err_rx:
+ free(fec->tbd_base);
+err_tx:
+ return -ENOMEM;
+}
+
+static void fec_free_descs(struct fec_priv *fec)
+{
+ int i;
+
+ for (i = 0; i < FEC_RBD_NUM; i++)
+ free((void *)fec->rbd_base[i].data_pointer);
+ free(fec->rbd_base);
+ free(fec->tbd_base);
+}
+
+#ifdef CONFIG_PHYLIB
+int fec_probe(bd_t *bd, int dev_id, uint32_t base_addr,
+ struct mii_dev *bus, struct phy_device *phydev)
+#else
+static int fec_probe(bd_t *bd, int dev_id, uint32_t base_addr,
+ struct mii_dev *bus, int phy_id)
+#endif