X-Git-Url: https://git.kernelconcepts.de/?p=karo-tx-uboot.git;a=blobdiff_plain;f=drivers%2Fnet%2Ffec_mxc.c;h=61f2db834c3db2d55d0804b96332e8112b7881f9;hp=549d6486136204ed644a2c2ecba101d25db303ef;hb=05f69dca34ee96d087b984800a0cc6d360827c5a;hpb=d4940fc521db6220a714a800e72b5d700e5c9974 diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c index 549d648613..61f2db834c 100644 --- a/drivers/net/fec_mxc.c +++ b/drivers/net/fec_mxc.c @@ -11,15 +11,18 @@ #include #include #include +#include #include -#include "fec_mxc.h" +#include #include #include #include #include #include +#include "fec_mxc.h" + DECLARE_GLOBAL_DATA_PTR; /* @@ -48,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 @@ -66,13 +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) */ -}; - #ifdef CONFIG_FEC_MXC_SWAP_PACKET static void swap_packet(uint32_t *packet, int length) { @@ -91,7 +87,7 @@ static int fec_mdio_read(struct ethernet_regs *eth, uint8_t phyAddr, { uint32_t reg; /* convenient holder for the PHY register */ uint32_t phy; /* convenient holder for the PHY */ - uint32_t start; + ulong start; int val; /* @@ -111,6 +107,8 @@ static int fec_mdio_read(struct ethernet_regs *eth, uint8_t phyAddr, start = get_timer(0); while (!(readl(ð->ievent) & FEC_IEVENT_MII)) { if (get_timer(start) > (CONFIG_SYS_HZ / 1000)) { + if (readl(ð->ievent) & FEC_IEVENT_MII) + break; printf("Read MDIO failed...\n"); return -1; } @@ -125,7 +123,7 @@ static int fec_mdio_read(struct ethernet_regs *eth, uint8_t phyAddr, * it's now safe to read the PHY's register */ val = (unsigned short)readl(ð->mii_data); - debug("%s: phy: %02x reg:%02x val:%#x\n", __func__, phyAddr, + debug("%s: phy: %02x reg:%02x val:%#06x\n", __func__, phyAddr, regAddr, val); return val; } @@ -150,7 +148,7 @@ static int fec_mdio_write(struct ethernet_regs *eth, uint8_t phyAddr, { uint32_t reg; /* convenient holder for the PHY register */ uint32_t phy; /* convenient holder for the PHY */ - uint32_t start; + ulong start; reg = regAddr << FEC_MII_DATA_RA_SHIFT; phy = phyAddr << FEC_MII_DATA_PA_SHIFT; @@ -164,6 +162,8 @@ static int fec_mdio_write(struct ethernet_regs *eth, uint8_t phyAddr, start = get_timer(0); while (!(readl(ð->ievent) & FEC_IEVENT_MII)) { if (get_timer(start) > (CONFIG_SYS_HZ / 1000)) { + if (readl(ð->ievent) & FEC_IEVENT_MII) + break; printf("Write MDIO failed...\n"); return -1; } @@ -173,19 +173,20 @@ static int fec_mdio_write(struct ethernet_regs *eth, uint8_t phyAddr, * clear MII interrupt bit */ writel(FEC_IEVENT_MII, ð->ievent); - debug("%s: phy: %02x reg:%02x val:%#x\n", __func__, phyAddr, + debug("%s: phy: %02x reg:%02x val:%#06x\n", __func__, phyAddr, regAddr, data); return 0; } -int fec_phy_read(struct mii_dev *bus, int phyAddr, int dev_addr, int regAddr) +static int fec_phy_read(struct mii_dev *bus, int phyAddr, int dev_addr, + int regAddr) { return fec_mdio_read(bus->priv, phyAddr, regAddr); } -int fec_phy_write(struct mii_dev *bus, int phyAddr, int dev_addr, int regAddr, - u16 data) +static int fec_phy_write(struct mii_dev *bus, int phyAddr, int dev_addr, + int regAddr, u16 data) { return fec_mdio_write(bus->priv, phyAddr, regAddr, data); } @@ -202,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); @@ -253,26 +254,22 @@ static int miiphy_wait_aneg(struct eth_device *dev) } #endif -static int fec_rx_task_enable(struct fec_priv *fec) +static inline void fec_rx_task_enable(struct fec_priv *fec) { - writel(FEC_R_DES_ACTIVE_RDAR, &fec->eth->r_des_active); - return 0; + writel(FEC_X_DES_ACTIVE_TDAR, &fec->eth->r_des_active); } -static int fec_rx_task_disable(struct fec_priv *fec) +static inline void fec_rx_task_disable(struct fec_priv *fec) { - return 0; } -static int fec_tx_task_enable(struct fec_priv *fec) +static inline void fec_tx_task_enable(struct fec_priv *fec) { writel(FEC_X_DES_ACTIVE_TDAR, &fec->eth->x_des_active); - return 0; } -static int fec_tx_task_disable(struct fec_priv *fec) +static inline void fec_tx_task_disable(struct fec_priv *fec) { - return 0; } /** @@ -355,7 +352,7 @@ 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) @@ -418,7 +415,7 @@ static void fec_reg_setup(struct fec_priv *fec) */ static int fec_open(struct eth_device *edev) { - struct fec_priv *fec = (struct fec_priv *)edev->priv; + struct fec_priv *fec = edev->priv; int speed; uint32_t addr, size; int i; @@ -452,7 +449,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 @@ -503,6 +500,7 @@ static int fec_open(struct eth_device *edev) { u32 ecr = readl(&fec->eth->ecntrl) & ~FEC_ECNTRL_SPEED; u32 rcr = readl(&fec->eth->r_cntrl) & ~FEC_RCNTRL_RMII_10T; + if (speed == _1000BASET) ecr |= FEC_ECNTRL_SPEED; else if (speed != _100BASET) @@ -510,6 +508,14 @@ static int fec_open(struct eth_device *edev) writel(ecr, &fec->eth->ecntrl); writel(rcr, &fec->eth->r_cntrl); } +#elif defined(CONFIG_SOC_MX28) + { + u32 rcr = readl(&fec->eth->r_cntrl) & ~FEC_RCNTRL_RMII_10T; + + if (speed == _10BASET) + rcr |= FEC_RCNTRL_RMII_10T; + writel(rcr, &fec->eth->r_cntrl); + } #endif debug("%s:Speed=%i\n", __func__, speed); @@ -518,15 +524,13 @@ static int fec_open(struct eth_device *edev) */ fec_rx_task_enable(fec); - udelay(100000); +// udelay(100000); return 0; } static int fec_init(struct eth_device *dev, bd_t* bd) { - struct fec_priv *fec = (struct fec_priv *)dev->priv; - uint32_t mib_ptr = (uint32_t)&fec->eth->rmon_t_drop; - int i; + struct fec_priv *fec = dev->priv; /* Initialize MAC address */ fec_set_hwaddr(dev); @@ -555,11 +559,6 @@ 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 = mib_ptr; i <= mib_ptr + 0xfc; i += 4) - writel(0, i); - /* FIFO receive start register */ writel(0x520, &fec->eth->r_fstart); @@ -583,7 +582,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; - int counter = 0xffff; + int counter = 1000; /* * issue graceful stop command to the FEC transmitter if necessary @@ -596,7 +595,7 @@ static void fec_halt(struct eth_device *dev) * wait for graceful stop to register */ while ((counter--) && (!(readl(&fec->eth->ievent) & FEC_IEVENT_GRA))) - udelay(1); + udelay(100); /* * Disable SmartDMA tasks @@ -634,7 +633,7 @@ static int fec_send(struct eth_device *dev, void *packet, int length) * This routine transmits one frame. This routine only accepts * 6-byte Ethernet addresses. */ - struct fec_priv *fec = (struct fec_priv *)dev->priv; + struct fec_priv *fec = dev->priv; /* * Check for valid length of data. @@ -659,13 +658,14 @@ static int fec_send(struct eth_device *dev, void *packet, int length) flush_dcache_range(addr, end); writew(length, &fec->tbd_base[fec->tbd_index].data_length); - writel(addr, &fec->tbd_base[fec->tbd_index].data_pointer); + writel((unsigned long)packet, + &fec->tbd_base[fec->tbd_index].data_pointer); /* * update BD's status now * This block: * - is always the last in a chain (means no chain) - * - should transmitt the CRC + * - should transmit the CRC * - might be the last BD in the list, so the address counter should * wrap (-> keep the WRAP flag) */ @@ -717,6 +717,7 @@ 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) { @@ -744,6 +745,7 @@ 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) @@ -773,7 +775,6 @@ static int fec_recv(struct eth_device *dev) 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; @@ -783,8 +784,11 @@ static int fec_recv(struct eth_device *dev) * Check if any critical events have happened */ ievent = readl(&fec->eth->ievent); - writel(ievent, &fec->eth->ievent); - debug("fec_recv: ievent 0x%lx\n", ievent); + if (ievent) + writel(ievent, &fec->eth->ievent); + + if (ievent) + debug("fec_recv: ievent 0x%lx\n", ievent); if (ievent & FEC_IEVENT_BABR) { fec_halt(dev); fec_init(dev, fec->bd); @@ -825,20 +829,20 @@ static int fec_recv(struct eth_device *dev) invalidate_dcache_range(addr, addr + size); bd_status = readw(&rbd->status); - debug("fec_recv: status 0x%x\n", bd_status); - if (!(bd_status & FEC_RBD_EMPTY)) { + debug("fec_recv: status 0x%04x len %u\n", bd_status, + readw(&rbd->data_length) - 4); if ((bd_status & FEC_RBD_LAST) && !(bd_status & FEC_RBD_ERR) && ((readw(&rbd->data_length) - 4) > 14)) { /* * 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); @@ -847,16 +851,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(buff, frame->data, frame_length); - NetReceive(buff, frame_length); + 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); } /* @@ -879,8 +882,8 @@ static int fec_recv(struct eth_device *dev) fec_rx_task_enable(fec); fec->rbd_index = (fec->rbd_index + 1) % FEC_RBD_NUM; + debug("fec_recv: stop\n"); } - debug("fec_recv: stop\n"); return len; } @@ -973,23 +976,20 @@ static int fec_probe(bd_t *bd, int dev_id, uint32_t base_addr, int ret = 0; /* create and fill edev struct */ - edev = (struct eth_device *)malloc(sizeof(struct eth_device)); + edev = calloc(sizeof(struct eth_device), 1); if (!edev) { puts("fec_mxc: not enough malloc memory for eth_device\n"); ret = -ENOMEM; goto err1; } - fec = (struct fec_priv *)malloc(sizeof(struct fec_priv)); + fec = calloc(sizeof(struct fec_priv), 1); if (!fec) { puts("fec_mxc: not enough malloc memory for fec_priv\n"); ret = -ENOMEM; goto err2; } - memset(edev, 0, sizeof(*edev)); - memset(fec, 0, sizeof(*fec)); - ret = fec_alloc_descs(fec); if (ret) goto err3; @@ -1033,7 +1033,10 @@ static int fec_probe(bd_t *bd, int dev_id, uint32_t base_addr, eth_register(edev); if (fec_get_hwaddr(edev, dev_id, ethaddr) == 0) { - debug("got MAC%d address from fuse: %pM\n", dev_id, ethaddr); + if (dev_id < 0) + debug("got MAC address from fuse: %pM\n", ethaddr); + else + debug("got MAC%d address from fuse: %pM\n", dev_id, ethaddr); memcpy(edev->enetaddr, ethaddr, 6); if (!getenv("ethaddr")) eth_setenv_enetaddr("ethaddr", ethaddr); @@ -1084,7 +1087,7 @@ int fecmxc_initialize_multi(bd_t *bd, int dev_id, int phy_id, uint32_t addr) #endif int ret; -#ifdef CONFIG_MX28 +#ifdef CONFIG_SOC_MX28 /* * The i.MX28 has two ethernet interfaces, but they are not equal. * Only the first one can access the MDIO bus. @@ -1098,7 +1101,8 @@ 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); + phydev = phy_find_by_mask(bus, phy_id < 0 ? 0xff : (1 << phy_id), + PHY_INTERFACE_MODE_RGMII); if (!phydev) { free(bus); return -ENOMEM;