diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/Makefile | 1 | ||||
-rw-r--r-- | drivers/net/ftmac110.c | 473 | ||||
-rw-r--r-- | drivers/net/ftmac110.h | 177 |
3 files changed, 651 insertions, 0 deletions
diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 1197f9a..9cf2983 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..579dcc7 --- /dev/null +++ b/drivers/net/ftmac110.c @@ -0,0 +1,473 @@ +/* + * Faraday 10/100Mbps Ethernet Controller + * + * (C) Copyright 2010 Faraday Technology + * Dante Su <dantesu@faraday-tech.com> + * + * 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 <common.h> +#include <command.h> +#include <malloc.h> +#include <net.h> +#include <asm/errno.h> +#include <asm/io.h> +#include <asm/dma-mapping.h> + +#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) +#include <miiphy.h> +#endif + +#include "ftmac110.h" + +#define CFG_RXDES_NUM 8 +#define CFG_TXDES_NUM 2 +#define CFG_XBUF_SIZE 1536 + +#define CFG_MDIORD_TIMEOUT (CONFIG_SYS_HZ >> 1) /* 500 ms */ +#define CFG_MDIOWR_TIMEOUT (CONFIG_SYS_HZ >> 1) /* 500 ms */ +#define CFG_LINKUP_TIMEOUT (CONFIG_SYS_HZ << 2) /* 4 sec */ + +/* + * 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); + + writel(tmp, ®s->phycr); + + for (ts = get_timer(0); get_timer(ts) < CFG_MDIORD_TIMEOUT; ) { + tmp = readl(®s->phycr); + if (tmp & PHYCR_READ) + continue; + break; + } + + if (tmp & PHYCR_READ) + printf("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); + + writel(phydata, ®s->phydr); + writel(tmp, ®s->phycr); + + for (ts = get_timer(0); get_timer(ts) < CFG_MDIOWR_TIMEOUT; ) { + if (readl(®s->phycr) & PHYCR_WRITE) + continue; + break; + } + + if (readl(®s->phycr) & PHYCR_WRITE) + printf("ftmac110: mdio write timeout\n"); +} + +static uint32_t ftmac110_phyqry(struct eth_device *dev) +{ + ulong ts; + uint32_t maccr; + uint16_t pa, tmp, bmsr, bmcr; + struct ftmac110_chip *chip = dev->priv; + + /* Default = 100Mbps Full */ + maccr = MACCR_100M | MACCR_FD; + + /* 1. find the phy device */ + for (pa = 0; pa < 32; ++pa) { + tmp = mdio_read(dev, pa, MII_PHYSID1); + if (tmp == 0xFFFF || tmp == 0x0000) + continue; + chip->phy_addr = pa; + break; + } + if (pa >= 32) { + puts("ftmac110: phy device not found!\n"); + goto exit; + } + + /* 2. wait until link-up & auto-negotiation complete */ + chip->lnkup = 0; + bmcr = mdio_read(dev, chip->phy_addr, MII_BMCR); + ts = get_timer(0); + do { + bmsr = mdio_read(dev, chip->phy_addr, MII_BMSR); + chip->lnkup = (bmsr & BMSR_LSTATUS) ? 1 : 0; + if (!chip->lnkup) + continue; + if (!(bmcr & BMCR_ANENABLE) || (bmsr & BMSR_ANEGCOMPLETE)) + break; + } while (get_timer(ts) < CFG_LINKUP_TIMEOUT); + if (!chip->lnkup) { + puts("ftmac110: link down\n"); + goto exit; + } + if (!(bmcr & BMCR_ANENABLE)) + puts("ftmac110: auto negotiation disabled\n"); + else if (!(bmsr & BMSR_ANEGCOMPLETE)) + puts("ftmac110: auto negotiation timeout\n"); + + /* 3. derive MACCR */ + if ((bmcr & BMCR_ANENABLE) && (bmsr & BMSR_ANEGCOMPLETE)) { + tmp = mdio_read(dev, chip->phy_addr, MII_ADVERTISE); + tmp &= mdio_read(dev, chip->phy_addr, MII_LPA); + 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 { + if (bmcr & BMCR_SPEED100) + maccr = MACCR_100M; + else + maccr = 0; + if (bmcr & BMCR_FULLDPLX) + maccr |= MACCR_FD; + } + +exit: + printf("ftmac110: %d Mbps, %s\n", + (maccr & MACCR_100M) ? 100 : 10, + (maccr & MACCR_FD) ? "Full" : "half"); + 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].ct[0] = 0; + } + chip->txd_idx = 0; + + /* 1-2. Init rx ring */ + for (i = 0; i < CFG_RXDES_NUM; ++i) { + /* owned by HW */ + chip->rxd[i].ct[0] = cpu_to_le32(FTMAC110_RXCT0_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; + + /* 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->rxba); + writel(chip->txd_dma, ®s->txba); + /* interrupt at each tx/rx */ + writel(ITC_DEFAULT, ®s->itc); + /* no tx pool, rx poll = 1 normal cycle */ + writel(APTC_DEFAULT, ®s->aptc); + /* rx threshold = [6/8 fifo, 2/8 fifo] */ + writel(DBLAC_DEFAULT, ®s->dblac); + /* disable & clear all interrupt status */ + chip->imr = 0; + writel(ISR_ALL, ®s->isr); + writel(chip->imr, ®s->imr); + /* enable mac */ + 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 *pkt, int len) +{ + struct ftmac110_chip *chip = dev->priv; + struct ftmac110_regs __iomem *regs = chip->regs; + struct ftmac110_txd *des; + + if (!chip->lnkup) + return 0; + + if (len <= 0 || len > CFG_XBUF_SIZE) { + printf("ftmac110: bad tx pkt len(%d)\n", len); + return 0; + } + + len = max(60, len); + + des = &chip->txd[chip->txd_idx]; + if (le32_to_cpu(des->ct[0]) & FTMAC110_TXCT0_OWNER) { + /* kick-off Tx DMA */ + writel(0xffffffff, ®s->txpd); + printf("ftmac110: out of txd\n"); + return 0; + } + + memcpy(des->vbuf, (void *)pkt, len); + dma_map_single(des->vbuf, len, DMA_TO_DEVICE); + + /* update len, fts and lts */ + des->ct[1] &= cpu_to_le32(FTMAC110_TXCT1_END); + des->ct[1] |= cpu_to_le32(FTMAC110_TXCT1_LEN(len) + | FTMAC110_TXCT1_FTS | FTMAC110_TXCT1_LTS); + + /* set owner bit and clear others */ + des->ct[0] = cpu_to_le32(FTMAC110_TXCT0_OWNER); + + /* kick-off Tx DMA */ + writel(0xffffffff, ®s->txpd); + + chip->txd_idx = (chip->txd_idx + 1) % CFG_TXDES_NUM; + + return len; +} + +static int ftmac110_recv(struct eth_device *dev) +{ + struct ftmac110_chip *chip = dev->priv; + struct ftmac110_rxd *des; + uint32_t ct0, len, rlen = 0; + uint8_t *buf; + + if (!chip->lnkup) + return 0; + + do { + des = &chip->rxd[chip->rxd_idx]; + ct0 = le32_to_cpu(des->ct[0]); + if (ct0 & FTMAC110_RXCT0_OWNER) + break; + + len = FTMAC110_RXCT0_LEN(ct0); + buf = des->vbuf; + + if (ct0 & FTMAC110_RXCT0_ERRMASK) { + printf("ftmac110: rx error\n"); + } else { + dma_map_single(buf, len, DMA_FROM_DEVICE); + NetReceive(buf, len); + rlen += len; + } + + /* owned by hardware */ + des->ct[0] = cpu_to_le32(FTMAC110_RXCT0_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].ct[1] = 0; + chip->txd[i].ct[0] = 0; /* owned by SW */ + } + chip->txd[i - 1].ct[1] |= cpu_to_le32(FTMAC110_TXCT1_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].ct[1] = cpu_to_le32(CFG_XBUF_SIZE); + chip->rxd[i].ct[0] = cpu_to_le32(FTMAC110_RXCT0_OWNER); + } + chip->rxd[i - 1].ct[1] |= cpu_to_le32(FTMAC110_RXCT1_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..5b2d23b --- /dev/null +++ b/drivers/net/ftmac110.h @@ -0,0 +1,177 @@ +/* + * Faraday 10/100Mbps Ethernet Controller + * + * (C) Copyright 2010 Faraday Technology + * Dante Su <dantesu@faraday-tech.com> + * + * 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 Register */ + uint32_t txpd; /* 0x18: Tx Poll Demand Register */ + uint32_t rxpd; /* 0x1c: Rx Poll Demand Register */ + uint32_t txba; /* 0x20: Tx Ring Base Address Register */ + uint32_t rxba; /* 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_ALL 0x3ff +#define ISR_PHYSTCHG (1 << 9) /* phy status change */ +#define ISR_AHBERR (1 << 8) /* bus error */ +#define ISR_RXLOST (1 << 7) /* rx lost */ +#define ISR_RXFIFO (1 << 6) /* rx to fifo */ +#define ISR_TXLOST (1 << 5) /* tx lost */ +#define ISR_TXOK (1 << 4) /* tx to ethernet */ +#define ISR_NOTXBUF (1 << 3) /* out of tx buffer */ +#define ISR_TXFIFO (1 << 2) /* tx to fifo */ +#define ISR_NORXBUF (1 << 1) /* out of rx buffer */ +#define ISR_RXOK (1 << 0) /* rx to buffer */ + +/* + * MACCR control bits + */ +#define MACCR_100M (1 << 18) /* 100Mbps mode */ +#define MACCR_RXBCST (1 << 17) /* rx broadcast packet */ +#define MACCR_RXMCST (1 << 16) /* rx multicast packet */ +#define MACCR_FD (1 << 15) /* full duplex */ +#define MACCR_CRCAPD (1 << 14) /* tx crc append */ +#define MACCR_RXALL (1 << 12) /* rx all packets */ +#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 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) /* tx packet even it's crc error */ +#define MACCR_LOOPBACK (1 << 3) /* loop-back */ +#define MACCR_RESET (1 << 2) /* reset */ +#define MACCR_RXDMAEN (1 << 1) /* rx dma enable */ +#define MACCR_TXDMAEN (1 << 0) /* tx dma enable */ + +/* + * PHYCR control bits + */ +#define PHYCR_READ (1 << 26) +#define PHYCR_WRITE (1 << 27) +#define PHYCR_REG_SHIFT 21 +#define PHYCR_ADDR_SHIFT 16 + +/* + * ITC control bits + */ + +/* Tx Cycle Length */ +#define ITC_TX_CYCLONG (1 << 15) /* 100Mbps=81.92us; 10Mbps=819.2us */ +#define ITC_TX_CYCNORM (0 << 15) /* 100Mbps=5.12us; 10Mbps=51.2us */ +/* Tx Threshold: Aggregate n interrupts as 1 interrupt */ +#define ITC_TX_THR(n) (((n) & 0x7) << 12) +/* Tx Interrupt Timeout = n * Tx Cycle */ +#define ITC_TX_ITMO(n) (((n) & 0xf) << 8) +/* Rx Cycle Length */ +#define ITC_RX_CYCLONG (1 << 7) /* 100Mbps=81.92us; 10Mbps=819.2us */ +#define ITC_RX_CYCNORM (0 << 7) /* 100Mbps=5.12us; 10Mbps=51.2us */ +/* Rx Threshold: Aggregate n interrupts as 1 interrupt */ +#define ITC_RX_THR(n) (((n) & 0x7) << 4) +/* Rx Interrupt Timeout = n * Rx Cycle */ +#define ITC_RX_ITMO(n) (((n) & 0xf) << 0) + +#define ITC_DEFAULT \ + (ITC_TX_THR(1) | ITC_TX_ITMO(0) | ITC_RX_THR(1) | ITC_RX_ITMO(0)) + +/* + * APTC contrl bits + */ + +/* Tx Cycle Length */ +#define APTC_TX_CYCLONG (1 << 12) /* 100Mbps=81.92us; 10Mbps=819.2us */ +#define APTC_TX_CYCNORM (0 << 12) /* 100Mbps=5.12us; 10Mbps=51.2us */ +/* Tx Poll Timeout = n * Tx Cycle, 0=No auto polling */ +#define APTC_TX_PTMO(n) (((n) & 0xf) << 8) +/* Rx Cycle Length */ +#define APTC_RX_CYCLONG (1 << 4) /* 100Mbps=81.92us; 10Mbps=819.2us */ +#define APTC_RX_CYCNORM (0 << 4) /* 100Mbps=5.12us; 10Mbps=51.2us */ +/* Rx Poll Timeout = n * Rx Cycle, 0=No auto polling */ +#define APTC_RX_PTMO(n) (((n) & 0xf) << 0) + +#define APTC_DEFAULT (APTC_TX_PTMO(0) | APTC_RX_PTMO(1)) + +/* + * DBLAC contrl bits + */ +#define DBLAC_BURST_MAX_ANY (0 << 14) /* un-limited */ +#define DBLAC_BURST_MAX_32X4 (2 << 14) /* max = 32 x 4 bytes */ +#define DBLAC_BURST_MAX_64X4 (3 << 14) /* max = 64 x 4 bytes */ +#define DBLAC_RXTHR_EN (1 << 9) /* enable rx threshold arbitration */ +#define DBLAC_RXTHR_HIGH(n) (((n) & 0x7) << 6) /* upper bound = n/8 fifo */ +#define DBLAC_RXTHR_LOW(n) (((n) & 0x7) << 3) /* lower bound = n/8 fifo */ +#define DBLAC_BURST_CAP16 (1 << 2) /* support burst 16 */ +#define DBLAC_BURST_CAP8 (1 << 1) /* support burst 8 */ +#define DBLAC_BURST_CAP4 (1 << 0) /* support burst 4 */ + +#define DBLAC_DEFAULT \ + (DBLAC_RXTHR_EN | DBLAC_RXTHR_HIGH(6) | DBLAC_RXTHR_LOW(2)) + +/* + * descriptor structure + */ +struct ftmac110_rxd { + uint32_t ct[2]; + uint32_t buf; + void *vbuf; /* reserved */ +}; + +#define FTMAC110_RXCT0_OWNER BIT_MASK(31) /* owner: 1=HW, 0=SW */ +#define FTMAC110_RXCT0_FRS BIT_MASK(29) /* first pkt desc */ +#define FTMAC110_RXCT0_LRS BIT_MASK(28) /* last pkt desc */ +#define FTMAC110_RXCT0_ODDNB BIT_MASK(22) /* odd nibble */ +#define FTMAC110_RXCT0_RUNT BIT_MASK(21) /* runt pkt */ +#define FTMAC110_RXCT0_FTL BIT_MASK(20) /* frame too long */ +#define FTMAC110_RXCT0_CRC BIT_MASK(19) /* pkt crc error */ +#define FTMAC110_RXCT0_ERR BIT_MASK(18) /* bus error */ +#define FTMAC110_RXCT0_ERRMASK (0x1f << 18) /* all errors */ +#define FTMAC110_RXCT0_BCST BIT_MASK(17) /* Bcst pkt */ +#define FTMAC110_RXCT0_MCST BIT_MASK(16) /* Mcst pkt */ +#define FTMAC110_RXCT0_LEN(x) ((x) & 0x7ff) + +#define FTMAC110_RXCT1_END BIT_MASK(31) +#define FTMAC110_RXCT1_BUFSZ(x) ((x) & 0x7ff) + +struct ftmac110_txd { + uint32_t ct[2]; + uint32_t buf; + void *vbuf; /* reserved */ +}; + +#define FTMAC110_TXCT0_OWNER BIT_MASK(31) /* owner: 1=HW, 0=SW */ +#define FTMAC110_TXCT0_COL 0x00000003 /* collision */ + +#define FTMAC110_TXCT1_END BIT_MASK(31) /* end of ring */ +#define FTMAC110_TXCT1_TXIC BIT_MASK(30) /* tx done interrupt */ +#define FTMAC110_TXCT1_TX2FIC BIT_MASK(29) /* tx fifo interrupt */ +#define FTMAC110_TXCT1_FTS BIT_MASK(28) /* first pkt desc */ +#define FTMAC110_TXCT1_LTS BIT_MASK(27) /* last pkt desc */ +#define FTMAC110_TXCT1_LEN(x) ((x) & 0x7ff) + +#endif /* FTMAC110_H */ |