]> git.kernelconcepts.de Git - karo-tx-uboot.git/blobdiff - drivers/net/fec_mxc.c
net: fec: use correct sizes to clear and flush descriptors
[karo-tx-uboot.git] / drivers / net / fec_mxc.c
index 63f03e6202fed61f3229837541eb505104888d9a..19eb25c6173813aa4393db84a2c11ca1bb42df92 100644 (file)
@@ -51,7 +51,7 @@ DECLARE_GLOBAL_DATA_PTR;
  * The i.MX28 operates with packets in big endian. We need to swap them before
  * sending and after receiving.
  */
-#ifdef CONFIG_MX28
+#ifdef CONFIG_SOC_MX28
 #define CONFIG_FEC_MXC_SWAP_PACKET
 #endif
 
@@ -69,15 +69,6 @@ DECLARE_GLOBAL_DATA_PTR;
 
 #undef DEBUG
 
-struct nbuf {
-       uint8_t data[1500];     /**< actual data */
-       int length;             /**< actual length */
-       int used;               /**< buffer in use or not */
-       uint8_t head[16];       /**< MAC header(6 + 6 + 2) + 2(aligned) */
-};
-
-static int rx_idx;
-
 #ifdef CONFIG_FEC_MXC_SWAP_PACKET
 static void swap_packet(uint32_t *packet, int length)
 {
@@ -119,7 +110,7 @@ static int fec_mdio_read(struct ethernet_regs *eth, uint8_t phyAddr,
                        if (readl(&eth->ievent) & FEC_IEVENT_MII)
                                break;
                        printf("Read MDIO failed...\n");
-                       return -1;
+                       return -ETIMEDOUT;
                }
        }
 
@@ -174,7 +165,7 @@ static int fec_mdio_write(struct ethernet_regs *eth, uint8_t phyAddr,
                        if (readl(&eth->ievent) & FEC_IEVENT_MII)
                                break;
                        printf("Write MDIO failed...\n");
-                       return -1;
+                       return -ETIMEDOUT;
                }
        }
 
@@ -212,7 +203,7 @@ static int miiphy_restart_aneg(struct eth_device *dev)
         * Wake up from sleep if necessary
         * Reset PHY, then delay 300ns
         */
-#ifdef CONFIG_MX27
+#ifdef CONFIG_SOC_MX27
        fec_mdio_write(eth, fec->phy_id, MII_DCOUNTER, 0x00FF);
 #endif
        fec_mdio_write(eth, fec->phy_id, MII_BMCR, BMCR_RESET);
@@ -236,7 +227,7 @@ static int miiphy_restart_aneg(struct eth_device *dev)
 
 static int miiphy_wait_aneg(struct eth_device *dev)
 {
-       uint32_t start;
+       ulong start;
        int status;
        struct fec_priv *fec = (struct fec_priv *)dev->priv;
        struct ethernet_regs *eth = fec->bus->priv;
@@ -248,14 +239,14 @@ static int miiphy_wait_aneg(struct eth_device *dev)
        do {
                if (get_timer(start) > (CONFIG_SYS_HZ * 5)) {
                        printf("%s: Autonegotiation timeout\n", dev->name);
-                       return -1;
+                       return -ETIMEDOUT;
                }
 
                status = fec_mdio_read(eth, fec->phy_id, MII_BMSR);
                if (status < 0) {
                        printf("%s: Autonegotiation failed. status: %d\n",
                                        dev->name, status);
-                       return -1;
+                       return status;
                }
        } while (!(status & BMSR_LSTATUS));
 
@@ -265,7 +256,7 @@ static int miiphy_wait_aneg(struct eth_device *dev)
 
 static inline void fec_rx_task_enable(struct fec_priv *fec)
 {
-       writel(1 << 24, &fec->eth->r_des_active);
+       writel(FEC_X_DES_ACTIVE_TDAR, &fec->eth->r_des_active);
 }
 
 static inline void fec_rx_task_disable(struct fec_priv *fec)
@@ -274,7 +265,7 @@ static inline void fec_rx_task_disable(struct fec_priv *fec)
 
 static inline void fec_tx_task_enable(struct fec_priv *fec)
 {
-       writel(1 << 24, &fec->eth->x_des_active);
+       writel(FEC_X_DES_ACTIVE_TDAR, &fec->eth->x_des_active);
 }
 
 static inline void fec_tx_task_disable(struct fec_priv *fec)
@@ -292,19 +283,20 @@ static inline void fec_tx_task_disable(struct fec_priv *fec)
  */
 static void fec_rbd_init(struct fec_priv *fec, int count, int dsize)
 {
-       uint32_t size;
-       uint8_t *data;
+       size_t rbd_size, pkt_size;
+       void *data;
        int i;
 
        /*
         * Reload the RX descriptors with default values and wipe
         * the RX buffers.
         */
-       size = roundup(dsize, ARCH_DMA_MINALIGN);
+       pkt_size = roundup(dsize, ARCH_DMA_MINALIGN);
        for (i = 0; i < count; i++) {
-               data = (uint8_t *)fec->rbd_base[i].data_pointer;
+               data = (void *)fec->rbd_base[i].data_pointer;
                memset(data, 0, dsize);
-               flush_dcache_range((uint32_t)data, (uint32_t)data + size);
+               flush_dcache_range((unsigned long)data,
+                               (unsigned long)data + pkt_size);
 
                fec->rbd_base[i].status = FEC_RBD_EMPTY;
                fec->rbd_base[i].data_length = 0;
@@ -314,8 +306,9 @@ static void fec_rbd_init(struct fec_priv *fec, int count, int dsize)
        fec->rbd_base[i - 1].status = FEC_RBD_WRAP | FEC_RBD_EMPTY;
        fec->rbd_index = 0;
 
-       flush_dcache_range((unsigned)fec->rbd_base,
-                          (unsigned)fec->rbd_base + size);
+       rbd_size = roundup(sizeof(struct fec_bd) * count, ARCH_DMA_MINALIGN);
+       flush_dcache_range((unsigned long)fec->rbd_base,
+                          (unsigned long)fec->rbd_base + rbd_size);
 }
 
 /**
@@ -332,7 +325,7 @@ static void fec_rbd_init(struct fec_priv *fec, int count, int dsize)
  */
 static void fec_tbd_init(struct fec_priv *fec)
 {
-       unsigned addr = (unsigned)fec->tbd_base;
+       unsigned long addr = (unsigned long)fec->tbd_base;
        unsigned size = roundup(2 * sizeof(struct fec_bd),
                                ARCH_DMA_MINALIGN);
 
@@ -361,13 +354,13 @@ static int fec_get_hwaddr(struct eth_device *dev, int dev_id,
                                                unsigned char *mac)
 {
        imx_get_mac_from_fuse(dev_id, mac);
-       return !is_valid_ether_addr(mac);
+       return !is_valid_ethaddr(mac);
 }
 
 static int fec_set_hwaddr(struct eth_device *dev)
 {
        uchar *mac = dev->enetaddr;
-       struct fec_priv *fec = (struct fec_priv *)dev->priv;
+       struct fec_priv *fec = dev->priv;
 
        writel(0, &fec->eth->iaddr1);
        writel(0, &fec->eth->iaddr2);
@@ -458,7 +451,7 @@ static int fec_open(struct eth_device *edev)
         */
        writel(readl(&fec->eth->ecntrl) | FEC_ECNTRL_ETHER_EN,
                &fec->eth->ecntrl);
-#if defined(CONFIG_MX25) || defined(CONFIG_MX53) || defined(CONFIG_MX6SL)
+#if defined(CONFIG_SOC_MX25) || defined(CONFIG_SOC_MX53) || defined(CONFIG_SOC_MX6SL)
        udelay(100);
        /*
         * setup the MII gasket for RMII mode
@@ -517,7 +510,7 @@ static int fec_open(struct eth_device *edev)
                writel(ecr, &fec->eth->ecntrl);
                writel(rcr, &fec->eth->r_cntrl);
        }
-#elif defined(CONFIG_MX28)
+#elif defined(CONFIG_SOC_MX28)
        {
                u32 rcr = readl(&fec->eth->r_cntrl) & ~FEC_RCNTRL_RMII_10T;
 
@@ -540,8 +533,6 @@ static int fec_open(struct eth_device *edev)
 static int fec_init(struct eth_device *dev, bd_t* bd)
 {
        struct fec_priv *fec = dev->priv;
-       uint32_t *mib_ptr = (uint32_t *)&fec->eth->rmon_t_drop;
-       int i;
 
        /* Initialize MAC address */
        fec_set_hwaddr(dev);
@@ -570,14 +561,11 @@ static int fec_init(struct eth_device *dev, bd_t* bd)
        writel(0x00000000, &fec->eth->gaddr1);
        writel(0x00000000, &fec->eth->gaddr2);
 
-
-       /* clear MIB RAM */
-       for (i = 0; i <= 0xfc >> 2; i++)
-               writel(0, &mib_ptr[i]);
-
+       /* Do not access reserved register for i.MX6UL */
+#ifndef CONFIG_SOC_MX6UL
        /* FIFO receive start register */
        writel(0x520, &fec->eth->r_fstart);
-
+#endif
        /* size and address of each buffer */
        writel(FEC_MAX_PKT_SIZE, &fec->eth->emrbr);
        writel((uint32_t)fec->tbd_base, &fec->eth->etdsr);
@@ -597,7 +585,7 @@ static int fec_init(struct eth_device *dev, bd_t* bd)
  */
 static void fec_halt(struct eth_device *dev)
 {
-       struct fec_priv *fec = (struct fec_priv *)dev->priv;
+       struct fec_priv *fec = dev->priv;
        int counter = 1000;
 
        /*
@@ -656,7 +644,7 @@ static int fec_send(struct eth_device *dev, void *packet, int length)
         */
        if ((length > 1500) || (length <= 0)) {
                printf("Payload (%d) too large\n", length);
-               return -1;
+               return -EINVAL;
        }
 
        /*
@@ -665,7 +653,7 @@ static int fec_send(struct eth_device *dev, void *packet, int length)
         * engine. We also flush the packet to RAM here to avoid cache trouble.
         */
 #ifdef CONFIG_FEC_MXC_SWAP_PACKET
-       swap_packet((uint32_t *)packet, length);
+       swap_packet(packet, length);
 #endif
 
        addr = (uint32_t)packet;
@@ -733,10 +721,11 @@ static int fec_send(struct eth_device *dev, void *packet, int length)
        while (--timeout) {
                if (!(readl(&fec->eth->x_des_active) & FEC_X_DES_ACTIVE_TDAR))
                        break;
+               udelay(1);
        }
 
        if (!timeout) {
-               ret = -EINVAL;
+               ret = -ETIMEDOUT;
                goto out;
        }
 
@@ -760,10 +749,11 @@ static int fec_send(struct eth_device *dev, void *packet, int length)
                if (!(readw(&fec->tbd_base[fec->tbd_index].status) &
                    FEC_TBD_READY))
                        break;
+               udelay(1);
        }
 
        if (!timeout)
-               ret = -EINVAL;
+               ret = -ETIMEDOUT;
 
 out:
        debug("fec_send: status 0x%x index %d ret %i\n",
@@ -785,14 +775,14 @@ out:
  */
 static int fec_recv(struct eth_device *dev)
 {
-       struct fec_priv *fec = (struct fec_priv *)dev->priv;
+       struct fec_priv *fec = dev->priv;
        struct fec_bd *rbd = &fec->rbd_base[fec->rbd_index];
        unsigned long ievent;
        int frame_length, len = 0;
-       struct nbuf *frame;
        uint16_t bd_status;
        uint32_t addr, size, end;
        int i;
+       ALLOC_CACHE_ALIGN_BUFFER(uchar, buff, FEC_MAX_PKT_SIZE);
 
        /*
         * Check if any critical events have happened
@@ -851,13 +841,12 @@ static int fec_recv(struct eth_device *dev)
                        /*
                         * Get buffer address and size
                         */
-                       frame = (struct nbuf *)readl(&rbd->data_pointer);
+                       addr = readl(&rbd->data_pointer);
                        frame_length = readw(&rbd->data_length) - 4;
 
                        /*
                         * Invalidate data cache over the buffer
                         */
-                       addr = (uint32_t)frame;
                        end = roundup(addr + frame_length, ARCH_DMA_MINALIGN);
                        addr &= ~(ARCH_DMA_MINALIGN - 1);
                        invalidate_dcache_range(addr, end);
@@ -866,17 +855,15 @@ static int fec_recv(struct eth_device *dev)
                         *  Fill the buffer and pass it to upper layers
                         */
 #ifdef CONFIG_FEC_MXC_SWAP_PACKET
-                       swap_packet((uint32_t *)frame->data, frame_length);
+                       swap_packet((uint32_t *)addr, frame_length);
 #endif
-                       memcpy((void *)NetRxPackets[rx_idx], frame->data, frame_length);
-                       NetReceive(NetRxPackets[rx_idx], frame_length);
-                       rx_idx = (rx_idx + 1) % PKTBUFSRX;
+                       memcpy(buff, (char *)addr, frame_length);
+                       net_process_received_packet(buff, frame_length);
                        len = frame_length;
                } else {
                        if (bd_status & FEC_RBD_ERR)
-                               printf("error frame: 0x%08lx 0x%08x\n",
-                                               (ulong)rbd->data_pointer,
-                                               bd_status);
+                               printf("error frame: 0x%08x 0x%08x\n",
+                                      addr, bd_status);
                }
 
                /*
@@ -912,46 +899,47 @@ static void fec_set_dev_name(char *dest, int dev_id)
 
 static int fec_alloc_descs(struct fec_priv *fec)
 {
-       unsigned int size;
+       size_t tbd_size, rbd_size, pkt_size;
        int i;
-       uint8_t *data;
+       void *data;
 
        /* Allocate TX descriptors. */
-       size = roundup(2 * sizeof(struct fec_bd), ARCH_DMA_MINALIGN);
-       fec->tbd_base = memalign(ARCH_DMA_MINALIGN, size);
+       tbd_size = roundup(2 * sizeof(struct fec_bd), ARCH_DMA_MINALIGN);
+       fec->tbd_base = memalign(ARCH_DMA_MINALIGN, tbd_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);
+       rbd_size = roundup(FEC_RBD_NUM * sizeof(struct fec_bd), ARCH_DMA_MINALIGN);
+       fec->rbd_base = memalign(ARCH_DMA_MINALIGN, rbd_size);
        if (!fec->rbd_base)
                goto err_rx;
 
-       memset(fec->rbd_base, 0, size);
+       memset(fec->rbd_base, 0, rbd_size);
 
        /* Allocate RX buffers. */
 
        /* Maximum RX buffer size. */
-       size = roundup(FEC_MAX_PKT_SIZE, FEC_DMA_RX_MINALIGN);
+       pkt_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);
+               data = memalign(FEC_DMA_RX_MINALIGN, pkt_size);
                if (!data) {
                        printf("%s: error allocating rxbuf %d\n", __func__, i);
                        goto err_ring;
                }
 
-               memset(data, 0, size);
+               memset(data, 0, pkt_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);
+               flush_dcache_range((uint32_t)data, (uint32_t)data + pkt_size);
        }
 
        /* Mark the last RBD to close the ring. */
        fec->rbd_base[i - 1].status = FEC_RBD_WRAP | FEC_RBD_EMPTY;
+       flush_dcache_range((unsigned long)fec->rbd_base, rbd_size);
 
        fec->rbd_index = 0;
        fec->tbd_index = 0;
@@ -1104,12 +1092,14 @@ int fecmxc_initialize_multi(bd_t *bd, int dev_id, int phy_id, uint32_t addr)
 #endif
        int ret;
 
-#ifdef CONFIG_MX28
+#if defined(CONFIG_SOC_MX28)
        /*
         * The i.MX28 has two ethernet interfaces, but they are not equal.
         * Only the first one can access the MDIO bus.
         */
        base_mii = MXS_ENET0_BASE;
+#elif defined(FEC_MDIO_BASE_ADDR)
+       base_mii = FEC_MDIO_BASE_ADDR;
 #else
        base_mii = addr;
 #endif
@@ -1118,11 +1108,14 @@ int fecmxc_initialize_multi(bd_t *bd, int dev_id, int phy_id, uint32_t addr)
        if (!bus)
                return -ENOMEM;
 #ifdef CONFIG_PHYLIB
-       phydev = phy_find_by_mask(bus, 1 << phy_id, PHY_INTERFACE_MODE_RGMII);
+       static u8 phy_mask = 0xff;
+       phydev = phy_find_by_mask(bus, phy_id < 0 ? phy_mask : (1 << phy_id),
+                               PHY_INTERFACE_MODE_RGMII);
        if (!phydev) {
                free(bus);
                return -ENOMEM;
        }
+       phy_mask &= ~(1 << phydev->addr);
        ret = fec_probe(bd, dev_id, addr, bus, phydev);
 #else
        ret = fec_probe(bd, dev_id, addr, bus, phy_id);
@@ -1147,7 +1140,7 @@ int fecmxc_initialize(bd_t *bd)
 #ifndef CONFIG_PHYLIB
 int fecmxc_register_mii_postcall(struct eth_device *dev, int (*cb)(int))
 {
-       struct fec_priv *fec = (struct fec_priv *)dev->priv;
+       struct fec_priv *fec = dev->priv;
        fec->mii_postcall = cb;
        return 0;
 }