From patchwork Fri Apr 26 08:02:32 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kuo-Jung Su X-Patchwork-Id: 239715 X-Patchwork-Delegate: joe.hershberger@gmail.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id 1C6332C0113 for ; Fri, 26 Apr 2013 18:02:33 +1000 (EST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id D11EB4A148; Fri, 26 Apr 2013 10:02:30 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id M1LO7fSahXn8; Fri, 26 Apr 2013 10:02:30 +0200 (CEST) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 93CE84A0ED; Fri, 26 Apr 2013 10:02:19 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 3B4FF4A0C1 for ; Fri, 26 Apr 2013 10:01:53 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id bQc2nYdaywb6 for ; Fri, 26 Apr 2013 10:01:51 +0200 (CEST) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from mail-pa0-f51.google.com (mail-pa0-f51.google.com [209.85.220.51]) by theia.denx.de (Postfix) with ESMTPS id 1B9974A087 for ; Fri, 26 Apr 2013 10:01:48 +0200 (CEST) Received: by mail-pa0-f51.google.com with SMTP id jh10so2355954pab.38 for ; Fri, 26 Apr 2013 01:01:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=x-received:from:to:cc:subject:date:message-id:x-mailer:in-reply-to :references:in-reply-to:references; bh=CWhYbiXBUb+C4rwRRTZQdR6Y25DWKoSoPZPEJln0IS0=; b=tbo2Rea7aOJT0nWDdIz5U/SiUkAgSlCSMf/3mz2BiIwND3e+dxKKGCYy3LtNWIoZqk ut6YwWrZGBdWM8QSOr+nacK4K6QpuyY3LPszAM2oVoCuwAbANSVcJbiYnJZuzyzAyWaU iXSnB8Gfkej7vIbjkDxgllk4tAzl+9awdiT4I937NmDP0B/RRGbcI/7feWmooeyFGxzk xVRPvlwaeg0UAK5pBJegtc3Wocn/t0Fcz1bmkQtCaR3gz9mGIlACyA7JCvPnaycqWVSu Mz+Y592v85fQaUBT+QA3NjUpteIf5npQLRZ/JcNozUb2QnH/xlwW3XXA9NT2SF9ReZjs CBVQ== X-Received: by 10.68.221.1 with SMTP id qa1mr4302565pbc.125.1366963306852; Fri, 26 Apr 2013 01:01:46 -0700 (PDT) Received: from localhost.localdomain ([220.132.37.35]) by mx.google.com with ESMTPSA id lo7sm11690140pab.19.2013.04.26.01.01.44 for (version=TLSv1 cipher=DES-CBC3-SHA bits=168/168); Fri, 26 Apr 2013 01:01:46 -0700 (PDT) From: Kuo-Jung Su To: u-boot@lists.denx.de Date: Fri, 26 Apr 2013 16:02:32 +0800 Message-Id: <1366963360-2987-4-git-send-email-dantesu@gmail.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1366963360-2987-1-git-send-email-dantesu@gmail.com> References: <1366963360-2987-1-git-send-email-dantesu@gmail.com> In-Reply-To: <1366277139-29728-2-git-send-email-dantesu@gmail.com> References: <1366277139-29728-2-git-send-email-dantesu@gmail.com> Cc: Kuo-Jung Su Subject: [U-Boot] [PATCH v3 03/11] net: add Faraday FTMAC110 10/100Mbps ethernet support X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.11 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: u-boot-bounces@lists.denx.de Errors-To: u-boot-bounces@lists.denx.de From: Kuo-Jung Su Faraday FTMAC110 10/100Mbps supports half-word data transfer for Linux. However it has a weird DMA alignment issue: (1) Tx DMA Buffer Address: 1 bytes aligned: Invalid 2 bytes aligned: O.K 4 bytes aligned: O.K (2) Rx DMA Buffer Address: 1 bytes aligned: Invalid 2 bytes aligned: O.K 4 bytes aligned: Invalid!!! Signed-off-by: Kuo-Jung Su CC: Joe Hershberger --- drivers/net/Makefile | 1 + drivers/net/ftmac110.c | 471 ++++++++++++++++++++++++++++++++++++++++++++++++ drivers/net/ftmac110.h | 126 +++++++++++++ include/netdev.h | 1 + 4 files changed, 599 insertions(+) create mode 100644 drivers/net/ftmac110.c create mode 100644 drivers/net/ftmac110.h diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 786a656..0e23817 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -46,6 +46,7 @@ COBJS-$(CONFIG_ETHOC) += ethoc.o COBJS-$(CONFIG_FEC_MXC) += fec_mxc.o COBJS-$(CONFIG_FSLDMAFEC) += fsl_mcdmafec.o mcfmii.o COBJS-$(CONFIG_FTGMAC100) += ftgmac100.o +COBJS-$(CONFIG_FTMAC110) += ftmac110.o COBJS-$(CONFIG_FTMAC100) += ftmac100.o COBJS-$(CONFIG_GRETH) += greth.o COBJS-$(CONFIG_INCA_IP_SWITCH) += inca-ip_sw.o diff --git a/drivers/net/ftmac110.c b/drivers/net/ftmac110.c new file mode 100644 index 0000000..04f886f --- /dev/null +++ b/drivers/net/ftmac110.c @@ -0,0 +1,471 @@ +/* + * Faraday 10/100Mbps Ethernet Controller + * + * (C) Copyright 2010 Faraday Technology + * Dante Su + * + * This file is released under the terms of GPL v2 and any later version. + * See the file COPYING in the root directory of the source tree for details. + */ + +#include +#include +#include +#include +#include +#include +#include + +#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) +#include +#endif + +#include "ftmac110.h" + +#define CFG_RXDES_NUM 8 +#define CFG_TXDES_NUM 2 +#define CFG_XBUF_SIZE 1536 + +/* + * FTMAC110 DMA design issue + * + * Its DMA engine has a weird restriction that its Rx DMA engine + * accepts only 16-bits aligned address, 32-bits aligned is not + * acceptable. However this restriction does not apply to Tx DMA. + * + * Conclusion: + * (1) Tx DMA Buffer Address: + * 1 bytes aligned: Invalid + * 2 bytes aligned: O.K + * 4 bytes aligned: O.K (-> u-boot ZeroCopy is possible) + * (2) Rx DMA Buffer Address: + * 1 bytes aligned: Invalid + * 2 bytes aligned: O.K + * 4 bytes aligned: Invalid + */ + +struct ftmac110_chip { + void __iomem *regs; + uint32_t imr; + uint32_t maccr; + uint32_t lnkup; + uint32_t phy_addr; + + struct ftmac110_rxd *rxd; + ulong rxd_dma; + uint32_t rxd_idx; + + struct ftmac110_txd *txd; + ulong txd_dma; + uint32_t txd_idx; +}; + +static int ftmac110_reset(struct eth_device *dev); + +static uint16_t mdio_read(struct eth_device *dev, + uint8_t phyaddr, uint8_t phyreg) +{ + struct ftmac110_chip *chip = dev->priv; + struct ftmac110_regs __iomem *regs = chip->regs; + uint32_t tmp, ts; + uint16_t ret = 0xffff; + + tmp = PHYCR_READ + | (phyaddr << PHYCR_ADDR_SHIFT) + | (phyreg << PHYCR_REG_SHIFT) + | 0x30000000; + + writel(tmp, ®s->phycr); + + for (ts = get_timer(0); get_timer(ts) < 1000; ) { + tmp = readl(®s->phycr); + if (tmp & PHYCR_READ) + continue; + break; + } + + if (tmp & PHYCR_READ) + debug("ftmac110: mdio read timeout\n"); + else + ret = (uint16_t)(tmp & 0xffff); + + return ret; +} + +static void mdio_write(struct eth_device *dev, + uint8_t phyaddr, uint8_t phyreg, uint16_t phydata) +{ + struct ftmac110_chip *chip = dev->priv; + struct ftmac110_regs __iomem *regs = chip->regs; + uint32_t tmp, ts; + + tmp = PHYCR_WRITE + | (phyaddr << PHYCR_ADDR_SHIFT) + | (phyreg << PHYCR_REG_SHIFT) + | 0x30000000; + + writel(phydata, ®s->phydr); + writel(tmp, ®s->phycr); + + for (ts = get_timer(0); get_timer(ts) < 1000; ) { + if (readl(®s->phycr) & PHYCR_WRITE) + continue; + break; + } + + if (readl(®s->phycr) & PHYCR_WRITE) + debug("ftmac110: mdio write timeout\n"); +} + +static uint32_t ftmac110_phyqry(struct eth_device *dev) +{ + ulong ts; + uint32_t maccr; + uint16_t pa, tmp; + struct ftmac110_chip *chip = dev->priv; + + maccr = MACCR_100M | MACCR_FD; + + /* 0. find the phy device */ + for (pa = 0; pa < 32; ++pa) { + tmp = mdio_read(dev, pa, MII_PHYSID1); + if (tmp == 0xFFFF || tmp == 0x0000) + continue; + break; + } + if (pa >= 32) { + puts("ftmac110: phy device not found!\n"); + return maccr; + } else { + chip->phy_addr = pa; + } + + /* 1. check link status */ + chip->lnkup = 0; + for (ts = get_timer(0); get_timer(ts) < 1000; ) { + if (mdio_read(dev, chip->phy_addr, MII_BMSR) + & BMSR_LSTATUS) { + chip->lnkup = 1; + break; + } + } + if (!chip->lnkup) { + puts("ftmac110: link down\n"); + goto exit; + } + + /* 2. check A/N status */ + for (ts = get_timer(0); get_timer(ts) < 1000; ) { + if (mdio_read(dev, chip->phy_addr, MII_BMSR) + & BMSR_ANEGCOMPLETE) + break; + } + if (get_timer(ts) >= 1000) { + puts("ftmac110: A/N failed\n"); + goto exit; + } + + /* 3. build MACCR with the PHY status */ + tmp = mdio_read(dev, chip->phy_addr, MII_ADVERTISE); + tmp &= mdio_read(dev, chip->phy_addr, MII_LPA); + + /* 3-1. 10/100Mbps Detection */ + if (tmp & LPA_100FULL) /* 100Mbps full-duplex */ + maccr = MACCR_100M | MACCR_FD; + else if (tmp & LPA_100HALF) /* 100Mbps half-duplex */ + maccr = MACCR_100M; + else if (tmp & LPA_10FULL) /* 10Mbps full-duplex */ + maccr = MACCR_FD; + else if (tmp & LPA_10HALF) /* 10Mbps half-duplex */ + maccr = 0; + else + maccr = MACCR_100M | MACCR_FD; + + printf("ftmac110: %d Mbps, %s\n", + (maccr & MACCR_100M) ? 100 : 10, + (maccr & MACCR_FD) ? "Full" : "half"); + +exit: + return maccr; +} + +static int ftmac110_reset(struct eth_device *dev) +{ + uint8_t *a; + uint32_t i, maccr; + struct ftmac110_chip *chip = dev->priv; + struct ftmac110_regs __iomem *regs = chip->regs; + + /* 1. MAC reset */ + writel(MACCR_RESET, ®s->maccr); + for (i = get_timer(0); get_timer(i) < 1000; ) { + if (readl(®s->maccr) & MACCR_RESET) + continue; + break; + } + if (readl(®s->maccr) & MACCR_RESET) { + printf("ftmac110: reset failed\n"); + return -ENXIO; + } + + /* 1-1. Init tx ring */ + for (i = 0; i < CFG_TXDES_NUM; ++i) { + /* owned by SW */ + chip->txd[i].ctrl = 0; + } + chip->txd_idx = 0; + + /* 1-2. Init rx ring */ + for (i = 0; i < CFG_RXDES_NUM; ++i) { + /* owned by HW */ + chip->rxd[i].ctrl = cpu_to_le32(FTMAC110_RXCTRL_OWNER); + } + chip->rxd_idx = 0; + + /* 2. PHY status query */ + maccr = ftmac110_phyqry(dev); + + /* 3. Fix up the MACCR value */ + chip->maccr = maccr | MACCR_CRCAPD | MACCR_RXALL | MACCR_RXRUNT + | MACCR_RXEN | MACCR_TXEN | MACCR_RXDMAEN | MACCR_TXDMAEN; + chip->imr = 0; + + /* 4. MAC address setup */ + a = dev->enetaddr; + writel(a[1] | (a[0] << 8), ®s->mac[0]); + writel(a[5] | (a[4] << 8) | (a[3] << 16) + | (a[2] << 24), ®s->mac[1]); + + /* 5. MAC registers setup */ + writel(chip->rxd_dma, ®s->rxbar); + writel(chip->txd_dma, ®s->txbar); + /* interrupt at every packet transmit/receive */ + writel(0x00001010, ®s->itc); + /* tx/rx poll interval=5.12us; rx_poll_cnt=1 */ + writel(0x00000001, ®s->aptc); + /* rx fifo: high=1536, low=512 */ + writel(0x00000390, ®s->dblac); + /* clear all interrupt status */ + writel(0x000003FF, ®s->isr); + writel(chip->imr, ®s->imr); + writel(chip->maccr, ®s->maccr); + + return 0; +} + +static int ftmac110_probe(struct eth_device *dev, bd_t *bis) +{ + debug("ftmac110: probe\n"); + + if (ftmac110_reset(dev)) + return -1; + + return 0; +} + +static void ftmac110_halt(struct eth_device *dev) +{ + struct ftmac110_chip *chip = dev->priv; + struct ftmac110_regs __iomem *regs = chip->regs; + + writel(0, ®s->imr); + writel(0, ®s->maccr); + + debug("ftmac110: halt\n"); +} + +static int ftmac110_send(struct eth_device *dev, void *packet, int length) +{ + struct ftmac110_chip *chip = dev->priv; + struct ftmac110_regs __iomem *regs = chip->regs; + struct ftmac110_txd *des; + + if (!chip->lnkup) + return 0; + + if (length <= 0 || length > CFG_XBUF_SIZE) { + printf("ftmac110: bad tx packet length(%d)\n", length); + return 0; + } + + if (length < 60) + length = 60; + + des = &chip->txd[chip->txd_idx]; + if (le32_to_cpu(des->ctrl) & FTMAC110_TXCTRL_OWNER) { + /* kick-off Tx DMA */ + writel(0xffffffff, ®s->txpd); + printf("ftmac110: out of txd\n"); + return 0; + } + + memcpy(des->vbuf, (void *)packet, length); + dma_map_single(des->vbuf, length, DMA_TO_DEVICE); + + /* update length, fts and lts */ + des->conf &= cpu_to_le32(0xe0000000); + des->conf |= cpu_to_le32(length + | FTMAC110_TXCONF_FTS | FTMAC110_TXCONF_LTS); + + /* set owner bit and clear others */ + des->ctrl = cpu_to_le32(FTMAC110_TXCTRL_OWNER); + + /* kick-off Tx DMA */ + writel(0xffffffff, ®s->txpd); + + chip->txd_idx = (chip->txd_idx + 1) % CFG_TXDES_NUM; + + return length; +} + +static int ftmac110_recv(struct eth_device *dev) +{ + struct ftmac110_chip *chip = dev->priv; + struct ftmac110_rxd *des; + uint32_t ctrl, len, rlen = 0; + uint8_t *buf; + + if (!chip->lnkup) + return 0; + + do { + des = &chip->rxd[chip->rxd_idx]; + ctrl = le32_to_cpu(des->ctrl); + if (ctrl & FTMAC110_RXCTRL_OWNER) + break; + + len = ctrl & FTMAC110_RXCTRL_LEN_MASK; + buf = des->vbuf; + + if (ctrl & FTMAC110_RXCTRL_ERRMASK) { + printf("ftmac110: rx error\n"); + } else { + dma_map_single(buf, len, DMA_FROM_DEVICE); + NetReceive(buf, len); + rlen += len; + } + + /* owned by hardware */ + des->ctrl = cpu_to_le32(FTMAC110_RXCTRL_OWNER); + + chip->rxd_idx = (chip->rxd_idx + 1) % CFG_RXDES_NUM; + } while (0); + + return rlen; +} + +#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) + +static int ftmac110_mdio_read( + const char *devname, uint8_t addr, uint8_t reg, uint16_t *value) +{ + int ret = 0; + struct eth_device *dev; + + dev = eth_get_dev_by_name(devname); + if (dev == NULL) { + printf("%s: no such device\n", devname); + ret = -1; + } else { + *value = mdio_read(dev, addr, reg); + } + + return ret; +} + +static int ftmac110_mdio_write( + const char *devname, uint8_t addr, uint8_t reg, uint16_t value) +{ + int ret = 0; + struct eth_device *dev; + + dev = eth_get_dev_by_name(devname); + if (dev == NULL) { + printf("%s: no such device\n", devname); + ret = -1; + } else { + mdio_write(dev, addr, reg, value); + } + + return ret; +} + +#endif /* #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) */ + +int ftmac110_initialize(bd_t *bis) +{ + int i, card_nr = 0; + struct eth_device *dev; + struct ftmac110_chip *chip; + + dev = malloc(sizeof(*dev) + sizeof(*chip)); + if (dev == NULL) { + panic("ftmac110: out of memory 1\n"); + return -1; + } + chip = (struct ftmac110_chip *)(dev + 1); + memset(dev, 0, sizeof(*dev) + sizeof(*chip)); + + sprintf(dev->name, "FTMAC110#%d", card_nr); + + dev->iobase = CONFIG_FTMAC110_BASE; + chip->regs = (void __iomem *)dev->iobase; + dev->priv = chip; + dev->init = ftmac110_probe; + dev->halt = ftmac110_halt; + dev->send = ftmac110_send; + dev->recv = ftmac110_recv; + + if (!eth_getenv_enetaddr_by_index("eth", card_nr, dev->enetaddr)) + eth_random_enetaddr(dev->enetaddr); + + /* allocate tx descriptors (it must be 16 bytes aligned) */ + chip->txd = dma_alloc_coherent( + sizeof(struct ftmac110_txd) * CFG_TXDES_NUM, &chip->txd_dma); + if (!chip->txd) + panic("ftmac110: out of memory 3\n"); + memset(chip->txd, 0, + sizeof(struct ftmac110_txd) * CFG_TXDES_NUM); + for (i = 0; i < CFG_TXDES_NUM; ++i) { + void *va = memalign(ARCH_DMA_MINALIGN, CFG_XBUF_SIZE); + if (!va) + panic("ftmac110: out of memory 4\n"); + chip->txd[i].vbuf = va; + chip->txd[i].buf = cpu_to_le32(virt_to_phys(va)); + chip->txd[i].conf = 0; + chip->txd[i].ctrl = 0; /* owned by SW */ + } + chip->txd[i - 1].conf |= cpu_to_le32(FTMAC110_TXCONF_END); + chip->txd_idx = 0; + + /* allocate rx descriptors (it must be 16 bytes aligned) */ + chip->rxd = dma_alloc_coherent( + sizeof(struct ftmac110_rxd) * CFG_RXDES_NUM, &chip->rxd_dma); + if (!chip->rxd) + panic("ftmac110: out of memory 4\n"); + memset((void *)chip->rxd, 0, + sizeof(struct ftmac110_rxd) * CFG_RXDES_NUM); + for (i = 0; i < CFG_RXDES_NUM; ++i) { + void *va = memalign(ARCH_DMA_MINALIGN, CFG_XBUF_SIZE + 2); + if (!va) + panic("ftmac110: out of memory 5\n"); + /* it needs to be exactly 2 bytes aligned */ + va = ((uint8_t *)va + 2); + chip->rxd[i].vbuf = va; + chip->rxd[i].buf = cpu_to_le32(virt_to_phys(va)); + chip->rxd[i].conf = cpu_to_le32(CFG_XBUF_SIZE); + chip->rxd[i].ctrl = cpu_to_le32(FTMAC110_RXCTRL_OWNER); + } + chip->rxd[i - 1].conf |= cpu_to_le32(FTMAC110_RXCONF_END); + chip->rxd_idx = 0; + + eth_register(dev); + +#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) + miiphy_register(dev->name, ftmac110_mdio_read, ftmac110_mdio_write); +#endif + + card_nr++; + + return card_nr; +} diff --git a/drivers/net/ftmac110.h b/drivers/net/ftmac110.h new file mode 100644 index 0000000..3db3468 --- /dev/null +++ b/drivers/net/ftmac110.h @@ -0,0 +1,126 @@ +/* + * Faraday 10/100Mbps Ethernet Controller + * + * (C) Copyright 2010 Faraday Technology + * Dante Su + * + * This file is released under the terms of GPL v2 and any later version. + * See the file COPYING in the root directory of the source tree for details. + */ + +#ifndef _FTMAC110_H +#define _FTMAC110_H + +struct ftmac110_regs { + uint32_t isr; /* 0x00: Interrups Status Register */ + uint32_t imr; /* 0x04: Interrupt Mask Register */ + uint32_t mac[2]; /* 0x08: MAC Address */ + uint32_t mht[2]; /* 0x10: Multicast Hash Table 0 Register */ + uint32_t txpd; /* 0x18: Transmit Poll Demand Register */ + uint32_t rxpd; /* 0x1c: Receive Poll Demand register */ + uint32_t txbar; /* 0x20: Tx Ring Base Address Register */ + uint32_t rxbar; /* 0x24: Rx Ring Base Address Register */ + uint32_t itc; /* 0x28: Interrupt Timer Control Register */ + uint32_t aptc; /* 0x2C: Automatic Polling Timer Control Register */ + uint32_t dblac; /* 0x30: DMA Burst Length&Arbitration Control */ + uint32_t revr; /* 0x34: Revision Register */ + uint32_t fear; /* 0x38: Feature Register */ + uint32_t rsvd[19]; + uint32_t maccr; /* 0x88: MAC Control Register */ + uint32_t macsr; /* 0x8C: MAC Status Register */ + uint32_t phycr; /* 0x90: PHY Control Register */ + uint32_t phydr; /* 0x94: PHY Data Register */ + uint32_t fcr; /* 0x98: Flow Control Register */ + uint32_t bpr; /* 0x9C: Back Pressure Register */ +}; + +/* Interrupt status/mask register(ISR/IMR) bits */ +#define ISR_PHYSTCHG (1 << 9) /* phy status change */ +#define ISR_AHBERR (1 << 8) /* bus error */ +#define ISR_RXLOST (1 << 7) /* rx lost due to fifo overflow */ +#define ISR_RXFIFO (1 << 6) /* rx to fifo */ +#define ISR_TXLOST (1 << 5) /* tx lost due to collision */ +#define ISR_TXOK (1 << 4) /* tx to ethernet */ +#define ISR_NOTXBUF (1 << 3) /* out of tx buffer */ +#define ISR_TXFIFO (1 << 2) /* packets transmitted to fifo */ +#define ISR_NORXBUF (1 << 1) /* out of rx buffer */ +#define ISR_RXOK (1 << 0) /* packets received to buffer (ram) */ + +/* MACC control bits */ +#define MACCR_100M (1 << 18) /* 100Mbps mode */ +#define MACCR_RXBCST (1 << 17) /* receive all broadcast packet */ +#define MACCR_RXMCST (1 << 16) /* receive all multicast packet */ +#define MACCR_FD (1 << 15) /* full duplex */ +#define MACCR_CRCAPD (1 << 14) /* append crc to transmit packet */ +#define MACCR_RXALL (1 << 12) /* ignore dst address */ +#define MACCR_RXFTL (1 << 11) /* rx packet even it's > 1518 byte */ +#define MACCR_RXRUNT (1 << 10) /* rx packet even it's < 64 byte */ +#define MACCR_RXMCSTHT (1 << 9) /* rx multicast per hash table */ +#define MACCR_RXEN (1 << 8) /* rx enable */ +#define MACCR_RXINHDTX (1 << 6) /* rx in half duplex tx */ +#define MACCR_TXEN (1 << 5) /* tx enable */ +#define MACCR_CRCDIS (1 << 4) /* rx packet even it's crc error */ +#define MACCR_LOOPBACK (1 << 3) /* Internal loop-back */ +#define MACCR_RESET (1 << 2) /* reset */ +#define MACCR_RXDMAEN (1 << 1) /* enable rx dma */ +#define MACCR_TXDMAEN (1 << 0) /* enable tx dma */ + +/* MDIO PHY bits */ +#define PHYCR_READ (1 << 26) +#define PHYCR_WRITE (1 << 27) +#define PHYCR_REG_SHIFT 21 +#define PHYCR_ADDR_SHIFT 16 + +/* + * descriptor structure + */ +struct ftmac110_rxd { + /* Hardware control fields */ + uint32_t ctrl; + uint32_t conf; + uint32_t buf; + + /* Software control field */ + void *vbuf; +}; + +#define FTMAC110_RXCTRL_OWNER BIT_MASK(31) /* owner: 1=HW, 0=SW */ +#define FTMAC110_RXCTRL_FRS BIT_MASK(29) /* 1st pkt desc */ +#define FTMAC110_RXCTRL_LRS BIT_MASK(28) /* last pkt desc */ +#define FTMAC110_RXCTRL_ODDNB BIT_MASK(22) /* odd nibble */ +#define FTMAC110_RXCTRL_RUNT BIT_MASK(21) /* runt pkt */ +#define FTMAC110_RXCTRL_FTL BIT_MASK(20) /* frame too long */ +#define FTMAC110_RXCTRL_CRC BIT_MASK(19) /* pkt crc error */ +#define FTMAC110_RXCTRL_ERR BIT_MASK(18) /* bus error */ +#define FTMAC110_RXCTRL_ERRMASK (0x1f << 18) /* all errors */ +#define FTMAC110_RXCTRL_BCST BIT_MASK(17) /* Bcst pkt */ +#define FTMAC110_RXCTRL_MCST BIT_MASK(16) /* Mcst pkt */ +#define FTMAC110_RXCTRL_LEN_MASK 0x7ff +#define FTMAC110_RXCTRL_LEN_SHIFT 0 + +#define FTMAC110_RXCONF_END BIT_MASK(31) +#define FTMAC110_RXCONF_BUFSZ_MASK 0x7ff +#define FTMAC110_RXCONF_BUFSZ_SHIFT 0 + +struct ftmac110_txd { + /* Hardware control fields */ + uint32_t ctrl; + uint32_t conf; + uint32_t buf; + + /* Software control field */ + void *vbuf; +}; + +#define FTMAC110_TXCTRL_OWNER BIT_MASK(31) /* owner: 1=HW, 0=SW */ +#define FTMAC110_TXCTRL_COL 0x00000003 /* collision */ + +#define FTMAC110_TXCONF_END BIT_MASK(31) /* end of ring */ +#define FTMAC110_TXCONF_TXIC BIT_MASK(30) /* tx done interrupt */ +#define FTMAC110_TXCONF_TX2FIC BIT_MASK(29) /* tx fifo interrupt */ +#define FTMAC110_TXCONF_FTS BIT_MASK(28) /* 1st pkt desc */ +#define FTMAC110_TXCONF_LTS BIT_MASK(27) /* last pkt desc */ +#define FTMAC110_TXCONF_BUFSZ_MASK 0x7ff +#define FTMAC110_TXCONF_BUFSZ_SHIFT 0 + +#endif /* FTMAC110_H */ diff --git a/include/netdev.h b/include/netdev.h index fd3e243..48c2fe5 100644 --- a/include/netdev.h +++ b/include/netdev.h @@ -67,6 +67,7 @@ int fecmxc_initialize(bd_t *bis); int fecmxc_initialize_multi(bd_t *bis, int dev_id, int phy_id, uint32_t addr); int ftgmac100_initialize(bd_t *bits); int ftmac100_initialize(bd_t *bits); +int ftmac110_initialize(bd_t *bits); int greth_initialize(bd_t *bis); void gt6426x_eth_initialize(bd_t *bis); int inca_switch_initialize(bd_t *bis);