Designware network driver support added. This is a Synopsys ethernet controller Signed-off-by: Vipin Kumar <vipin.kumar@st.com> Signed-off-by: Ben Warren <biggerbadderben@gmail.com>master
parent
c19a20d5bd
commit
5b1b1883ff
@ -0,0 +1,25 @@ |
||||
This driver supports Designware Ethernet Controller provided by Synopsis. |
||||
|
||||
The driver is enabled by CONFIG_DESIGNWARE_ETH. |
||||
|
||||
The driver has been developed and tested on SPEAr platforms. By default, the |
||||
MDIO interface works at 100/Full. #defining the below options in board |
||||
configuration file changes this behavior. |
||||
|
||||
Call an subroutine from respective board/.../board.c |
||||
designware_initialize(u32 id, ulong base_addr, u32 phy_addr); |
||||
|
||||
The various options suported by the driver are |
||||
1. CONFIG_DW_ALTDESCRIPTOR |
||||
Define this to use the Alternate/Enhanced Descriptor configurations. |
||||
1. CONFIG_DW_AUTONEG |
||||
Define this to autonegotiate with the host before proceeding with mac |
||||
level configuration. This obviates the definitions of CONFIG_DW_SPEED10M |
||||
and CONFIG_DW_DUPLEXHALF. |
||||
2. CONFIG_DW_SPEED10M |
||||
Define this to change the default behavior from 100Mbps to 10Mbps. |
||||
3. CONFIG_DW_DUPLEXHALF |
||||
Define this to change the default behavior from Full Duplex to Half. |
||||
4. CONFIG_DW_SEARCH_PHY |
||||
Define this to search the phy address. This would overwrite the value |
||||
passed as 3rd arg from designware_initialize routine. |
@ -0,0 +1,531 @@ |
||||
/*
|
||||
* (C) Copyright 2010 |
||||
* Vipin Kumar, ST Micoelectronics, vipin.kumar@st.com. |
||||
* |
||||
* See file CREDITS for list of people who contributed to this |
||||
* project. |
||||
* |
||||
* This program is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU General Public License as |
||||
* published by the Free Software Foundation; either version 2 of |
||||
* the License, or (at your option) any later version. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU General Public License |
||||
* along with this program; if not, write to the Free Software |
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, |
||||
* MA 02111-1307 USA |
||||
*/ |
||||
|
||||
/*
|
||||
* Designware ethernet IP driver for u-boot |
||||
*/ |
||||
|
||||
#include <common.h> |
||||
#include <miiphy.h> |
||||
#include <malloc.h> |
||||
#include <linux/err.h> |
||||
#include <asm/io.h> |
||||
#include "designware.h" |
||||
|
||||
static void tx_descs_init(struct eth_device *dev) |
||||
{ |
||||
struct dw_eth_dev *priv = dev->priv; |
||||
struct eth_dma_regs *dma_p = priv->dma_regs_p; |
||||
struct dmamacdescr *desc_table_p = &priv->tx_mac_descrtable[0]; |
||||
char *txbuffs = &priv->txbuffs[0]; |
||||
struct dmamacdescr *desc_p; |
||||
u32 idx; |
||||
|
||||
for (idx = 0; idx < CONFIG_TX_DESCR_NUM; idx++) { |
||||
desc_p = &desc_table_p[idx]; |
||||
desc_p->dmamac_addr = &txbuffs[idx * CONFIG_ETH_BUFSIZE]; |
||||
desc_p->dmamac_next = &desc_table_p[idx + 1]; |
||||
|
||||
#if defined(CONFIG_DW_ALTDESCRIPTOR) |
||||
desc_p->txrx_status &= ~(DESC_TXSTS_TXINT | DESC_TXSTS_TXLAST | |
||||
DESC_TXSTS_TXFIRST | DESC_TXSTS_TXCRCDIS | \
|
||||
DESC_TXSTS_TXCHECKINSCTRL | \
|
||||
DESC_TXSTS_TXRINGEND | DESC_TXSTS_TXPADDIS); |
||||
|
||||
desc_p->txrx_status |= DESC_TXSTS_TXCHAIN; |
||||
desc_p->dmamac_cntl = 0; |
||||
desc_p->txrx_status &= ~(DESC_TXSTS_MSK | DESC_TXSTS_OWNBYDMA); |
||||
#else |
||||
desc_p->dmamac_cntl = DESC_TXCTRL_TXCHAIN; |
||||
desc_p->txrx_status = 0; |
||||
#endif |
||||
} |
||||
|
||||
/* Correcting the last pointer of the chain */ |
||||
desc_p->dmamac_next = &desc_table_p[0]; |
||||
|
||||
writel((ulong)&desc_table_p[0], &dma_p->txdesclistaddr); |
||||
} |
||||
|
||||
static void rx_descs_init(struct eth_device *dev) |
||||
{ |
||||
struct dw_eth_dev *priv = dev->priv; |
||||
struct eth_dma_regs *dma_p = priv->dma_regs_p; |
||||
struct dmamacdescr *desc_table_p = &priv->rx_mac_descrtable[0]; |
||||
char *rxbuffs = &priv->rxbuffs[0]; |
||||
struct dmamacdescr *desc_p; |
||||
u32 idx; |
||||
|
||||
for (idx = 0; idx < CONFIG_RX_DESCR_NUM; idx++) { |
||||
desc_p = &desc_table_p[idx]; |
||||
desc_p->dmamac_addr = &rxbuffs[idx * CONFIG_ETH_BUFSIZE]; |
||||
desc_p->dmamac_next = &desc_table_p[idx + 1]; |
||||
|
||||
desc_p->dmamac_cntl = |
||||
(MAC_MAX_FRAME_SZ & DESC_RXCTRL_SIZE1MASK) | \
|
||||
DESC_RXCTRL_RXCHAIN; |
||||
|
||||
desc_p->txrx_status = DESC_RXSTS_OWNBYDMA; |
||||
} |
||||
|
||||
/* Correcting the last pointer of the chain */ |
||||
desc_p->dmamac_next = &desc_table_p[0]; |
||||
|
||||
writel((ulong)&desc_table_p[0], &dma_p->rxdesclistaddr); |
||||
} |
||||
|
||||
static void descs_init(struct eth_device *dev) |
||||
{ |
||||
tx_descs_init(dev); |
||||
rx_descs_init(dev); |
||||
} |
||||
|
||||
static int mac_reset(struct eth_device *dev) |
||||
{ |
||||
struct dw_eth_dev *priv = dev->priv; |
||||
struct eth_mac_regs *mac_p = priv->mac_regs_p; |
||||
struct eth_dma_regs *dma_p = priv->dma_regs_p; |
||||
|
||||
int timeout = CONFIG_MACRESET_TIMEOUT; |
||||
|
||||
writel(DMAMAC_SRST, &dma_p->busmode); |
||||
writel(MII_PORTSELECT, &mac_p->conf); |
||||
|
||||
do { |
||||
if (!(readl(&dma_p->busmode) & DMAMAC_SRST)) |
||||
return 0; |
||||
udelay(1000); |
||||
} while (timeout--); |
||||
|
||||
return -1; |
||||
} |
||||
|
||||
static int dw_write_hwaddr(struct eth_device *dev) |
||||
{ |
||||
struct dw_eth_dev *priv = dev->priv; |
||||
struct eth_mac_regs *mac_p = priv->mac_regs_p; |
||||
u32 macid_lo, macid_hi; |
||||
u8 *mac_id = &dev->enetaddr[0]; |
||||
|
||||
macid_lo = mac_id[0] + (mac_id[1] << 8) + \
|
||||
(mac_id[2] << 16) + (mac_id[3] << 24); |
||||
macid_hi = mac_id[4] + (mac_id[5] << 8); |
||||
|
||||
writel(macid_hi, &mac_p->macaddr0hi); |
||||
writel(macid_lo, &mac_p->macaddr0lo); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
static int dw_eth_init(struct eth_device *dev, bd_t *bis) |
||||
{ |
||||
struct dw_eth_dev *priv = dev->priv; |
||||
struct eth_mac_regs *mac_p = priv->mac_regs_p; |
||||
struct eth_dma_regs *dma_p = priv->dma_regs_p; |
||||
u32 conf; |
||||
|
||||
/* Reset ethernet hardware */ |
||||
if (mac_reset(dev) < 0) |
||||
return -1; |
||||
|
||||
writel(FIXEDBURST | PRIORXTX_41 | BURST_16, |
||||
&dma_p->busmode); |
||||
|
||||
writel(FLUSHTXFIFO | readl(&dma_p->opmode), &dma_p->opmode); |
||||
writel(STOREFORWARD | TXSECONDFRAME, &dma_p->opmode); |
||||
|
||||
conf = FRAMEBURSTENABLE | DISABLERXOWN; |
||||
|
||||
if (priv->speed != SPEED_1000M) |
||||
conf |= MII_PORTSELECT; |
||||
|
||||
if (priv->duplex == FULL_DUPLEX) |
||||
conf |= FULLDPLXMODE; |
||||
|
||||
writel(conf, &mac_p->conf); |
||||
|
||||
descs_init(dev); |
||||
|
||||
/*
|
||||
* Start/Enable xfer at dma as well as mac level |
||||
*/ |
||||
writel(readl(&dma_p->opmode) | RXSTART, &dma_p->opmode); |
||||
writel(readl(&dma_p->opmode) | TXSTART, &dma_p->opmode); |
||||
|
||||
writel(readl(&mac_p->conf) | RXENABLE, &mac_p->conf); |
||||
writel(readl(&mac_p->conf) | TXENABLE, &mac_p->conf); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
static int dw_eth_send(struct eth_device *dev, volatile void *packet, |
||||
int length) |
||||
{ |
||||
struct dw_eth_dev *priv = dev->priv; |
||||
struct eth_dma_regs *dma_p = priv->dma_regs_p; |
||||
u32 desc_num = priv->tx_currdescnum; |
||||
struct dmamacdescr *desc_p = &priv->tx_mac_descrtable[desc_num]; |
||||
|
||||
/* Check if the descriptor is owned by CPU */ |
||||
if (desc_p->txrx_status & DESC_TXSTS_OWNBYDMA) { |
||||
printf("CPU not owner of tx frame\n"); |
||||
return -1; |
||||
} |
||||
|
||||
memcpy((void *)desc_p->dmamac_addr, (void *)packet, length); |
||||
|
||||
#if defined(CONFIG_DW_ALTDESCRIPTOR) |
||||
desc_p->txrx_status |= DESC_TXSTS_TXFIRST | DESC_TXSTS_TXLAST; |
||||
desc_p->dmamac_cntl |= (length << DESC_TXCTRL_SIZE1SHFT) & \
|
||||
DESC_TXCTRL_SIZE1MASK; |
||||
|
||||
desc_p->txrx_status &= ~(DESC_TXSTS_MSK); |
||||
desc_p->txrx_status |= DESC_TXSTS_OWNBYDMA; |
||||
#else |
||||
desc_p->dmamac_cntl |= ((length << DESC_TXCTRL_SIZE1SHFT) & \
|
||||
DESC_TXCTRL_SIZE1MASK) | DESC_TXCTRL_TXLAST | \
|
||||
DESC_TXCTRL_TXFIRST; |
||||
|
||||
desc_p->txrx_status = DESC_TXSTS_OWNBYDMA; |
||||
#endif |
||||
|
||||
/* Test the wrap-around condition. */ |
||||
if (++desc_num >= CONFIG_TX_DESCR_NUM) |
||||
desc_num = 0; |
||||
|
||||
priv->tx_currdescnum = desc_num; |
||||
|
||||
/* Start the transmission */ |
||||
writel(POLL_DATA, &dma_p->txpolldemand); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
static int dw_eth_recv(struct eth_device *dev) |
||||
{ |
||||
struct dw_eth_dev *priv = dev->priv; |
||||
u32 desc_num = priv->rx_currdescnum; |
||||
struct dmamacdescr *desc_p = &priv->rx_mac_descrtable[desc_num]; |
||||
|
||||
u32 status = desc_p->txrx_status; |
||||
int length = 0; |
||||
|
||||
/* Check if the owner is the CPU */ |
||||
if (!(status & DESC_RXSTS_OWNBYDMA)) { |
||||
|
||||
length = (status & DESC_RXSTS_FRMLENMSK) >> \
|
||||
DESC_RXSTS_FRMLENSHFT; |
||||
|
||||
NetReceive(desc_p->dmamac_addr, length); |
||||
|
||||
/*
|
||||
* Make the current descriptor valid again and go to |
||||
* the next one |
||||
*/ |
||||
desc_p->txrx_status |= DESC_RXSTS_OWNBYDMA; |
||||
|
||||
/* Test the wrap-around condition. */ |
||||
if (++desc_num >= CONFIG_RX_DESCR_NUM) |
||||
desc_num = 0; |
||||
} |
||||
|
||||
priv->rx_currdescnum = desc_num; |
||||
|
||||
return length; |
||||
} |
||||
|
||||
static void dw_eth_halt(struct eth_device *dev) |
||||
{ |
||||
struct dw_eth_dev *priv = dev->priv; |
||||
|
||||
mac_reset(dev); |
||||
priv->tx_currdescnum = priv->rx_currdescnum = 0; |
||||
} |
||||
|
||||
static int eth_mdio_read(struct eth_device *dev, u8 addr, u8 reg, u16 *val) |
||||
{ |
||||
struct dw_eth_dev *priv = dev->priv; |
||||
struct eth_mac_regs *mac_p = priv->mac_regs_p; |
||||
u32 miiaddr; |
||||
int timeout = CONFIG_MDIO_TIMEOUT; |
||||
|
||||
miiaddr = ((addr << MIIADDRSHIFT) & MII_ADDRMSK) | \
|
||||
((reg << MIIREGSHIFT) & MII_REGMSK); |
||||
|
||||
writel(miiaddr | MII_CLKRANGE_150_250M | MII_BUSY, &mac_p->miiaddr); |
||||
|
||||
do { |
||||
if (!(readl(&mac_p->miiaddr) & MII_BUSY)) { |
||||
*val = readl(&mac_p->miidata); |
||||
return 0; |
||||
} |
||||
udelay(1000); |
||||
} while (timeout--); |
||||
|
||||
return -1; |
||||
} |
||||
|
||||
static int eth_mdio_write(struct eth_device *dev, u8 addr, u8 reg, u16 val) |
||||
{ |
||||
struct dw_eth_dev *priv = dev->priv; |
||||
struct eth_mac_regs *mac_p = priv->mac_regs_p; |
||||
u32 miiaddr; |
||||
int ret = -1, timeout = CONFIG_MDIO_TIMEOUT; |
||||
u16 value; |
||||
|
||||
writel(val, &mac_p->miidata); |
||||
miiaddr = ((addr << MIIADDRSHIFT) & MII_ADDRMSK) | \
|
||||
((reg << MIIREGSHIFT) & MII_REGMSK) | MII_WRITE; |
||||
|
||||
writel(miiaddr | MII_CLKRANGE_150_250M | MII_BUSY, &mac_p->miiaddr); |
||||
|
||||
do { |
||||
if (!(readl(&mac_p->miiaddr) & MII_BUSY)) |
||||
ret = 0; |
||||
udelay(1000); |
||||
} while (timeout--); |
||||
|
||||
/* Needed as a fix for ST-Phy */ |
||||
eth_mdio_read(dev, addr, reg, &value); |
||||
|
||||
return ret; |
||||
} |
||||
|
||||
#if defined(CONFIG_DW_SEARCH_PHY) |
||||
static int find_phy(struct eth_device *dev) |
||||
{ |
||||
int phy_addr = 0; |
||||
u16 ctrl, oldctrl; |
||||
|
||||
do { |
||||
eth_mdio_read(dev, phy_addr, PHY_BMCR, &ctrl); |
||||
oldctrl = ctrl & PHY_BMCR_AUTON; |
||||
|
||||
ctrl ^= PHY_BMCR_AUTON; |
||||
eth_mdio_write(dev, phy_addr, PHY_BMCR, ctrl); |
||||
eth_mdio_read(dev, phy_addr, PHY_BMCR, &ctrl); |
||||
ctrl &= PHY_BMCR_AUTON; |
||||
|
||||
if (ctrl == oldctrl) { |
||||
phy_addr++; |
||||
} else { |
||||
ctrl ^= PHY_BMCR_AUTON; |
||||
eth_mdio_write(dev, phy_addr, PHY_BMCR, ctrl); |
||||
|
||||
return phy_addr; |
||||
} |
||||
} while (phy_addr < 32); |
||||
|
||||
return -1; |
||||
} |
||||
#endif |
||||
|
||||
static int dw_reset_phy(struct eth_device *dev) |
||||
{ |
||||
struct dw_eth_dev *priv = dev->priv; |
||||
u16 ctrl; |
||||
int timeout = CONFIG_PHYRESET_TIMEOUT; |
||||
u32 phy_addr = priv->address; |
||||
|
||||
eth_mdio_write(dev, phy_addr, PHY_BMCR, PHY_BMCR_RESET); |
||||
do { |
||||
eth_mdio_read(dev, phy_addr, PHY_BMCR, &ctrl); |
||||
if (!(ctrl & PHY_BMCR_RESET)) |
||||
break; |
||||
udelay(1000); |
||||
} while (timeout--); |
||||
|
||||
if (timeout < 0) |
||||
return -1; |
||||
|
||||
#ifdef CONFIG_PHY_RESET_DELAY |
||||
udelay(CONFIG_PHY_RESET_DELAY); |
||||
#endif |
||||
return 0; |
||||
} |
||||
|
||||
static int configure_phy(struct eth_device *dev) |
||||
{ |
||||
struct dw_eth_dev *priv = dev->priv; |
||||
int phy_addr; |
||||
u16 bmcr, ctrl; |
||||
#if defined(CONFIG_DW_AUTONEG) |
||||
u16 bmsr; |
||||
u32 timeout; |
||||
u16 anlpar, btsr; |
||||
#endif |
||||
|
||||
#if defined(CONFIG_DW_SEARCH_PHY) |
||||
phy_addr = find_phy(dev); |
||||
if (phy_addr > 0) |
||||
priv->address = phy_addr; |
||||
else |
||||
return -1; |
||||
#endif |
||||
if (dw_reset_phy(dev) < 0) |
||||
return -1; |
||||
|
||||
#if defined(CONFIG_DW_AUTONEG) |
||||
bmcr = PHY_BMCR_AUTON | PHY_BMCR_RST_NEG | PHY_BMCR_100MB | \
|
||||
PHY_BMCR_DPLX | PHY_BMCR_1000_MBPS; |
||||
#else |
||||
bmcr = PHY_BMCR_100MB | PHY_BMCR_DPLX; |
||||
|
||||
#if defined(CONFIG_DW_SPEED10M) |
||||
bmcr &= ~PHY_BMCR_100MB; |
||||
#endif |
||||
#if defined(CONFIG_DW_DUPLEXHALF) |
||||
bmcr &= ~PHY_BMCR_DPLX; |
||||
#endif |
||||
#endif |
||||
if (eth_mdio_write(dev, phy_addr, PHY_BMCR, bmcr) < 0) |
||||
return -1; |
||||
|
||||
/* Read the phy status register and populate priv structure */ |
||||
#if defined(CONFIG_DW_AUTONEG) |
||||
timeout = CONFIG_AUTONEG_TIMEOUT; |
||||
do { |
||||
eth_mdio_read(dev, phy_addr, PHY_BMSR, &bmsr); |
||||
if (bmsr & PHY_BMSR_AUTN_COMP) |
||||
break; |
||||
udelay(1000); |
||||
} while (timeout--); |
||||
|
||||
eth_mdio_read(dev, phy_addr, PHY_ANLPAR, &anlpar); |
||||
eth_mdio_read(dev, phy_addr, PHY_1000BTSR, &btsr); |
||||
|
||||
if (btsr & (PHY_1000BTSR_1000FD | PHY_1000BTSR_1000HD)) { |
||||
priv->speed = SPEED_1000M; |
||||
if (btsr & PHY_1000BTSR_1000FD) |
||||
priv->duplex = FULL_DUPLEX; |
||||
else |
||||
priv->duplex = HALF_DUPLEX; |
||||
} else { |
||||
if (anlpar & PHY_ANLPAR_100) |
||||
priv->speed = SPEED_100M; |
||||
else |
||||
priv->speed = SPEED_10M; |
||||
|
||||
if (anlpar & (PHY_ANLPAR_10FD | PHY_ANLPAR_TXFD)) |
||||
priv->duplex = FULL_DUPLEX; |
||||
else |
||||
priv->duplex = HALF_DUPLEX; |
||||
} |
||||
#else |
||||
if (eth_mdio_read(dev, phy_addr, PHY_BMCR, &ctrl) < 0) |
||||
return -1; |
||||
|
||||
if (ctrl & PHY_BMCR_DPLX) |
||||
priv->duplex = FULL_DUPLEX; |
||||
else |
||||
priv->duplex = HALF_DUPLEX; |
||||
|
||||
if (ctrl & PHY_BMCR_1000_MBPS) |
||||
priv->speed = SPEED_1000M; |
||||
else if (ctrl & PHY_BMCR_100_MBPS) |
||||
priv->speed = SPEED_100M; |
||||
else |
||||
priv->speed = SPEED_10M; |
||||
#endif |
||||
return 0; |
||||
} |
||||
|
||||
#if defined(CONFIG_MII) |
||||
static int dw_mii_read(char *devname, u8 addr, u8 reg, u16 *val) |
||||
{ |
||||
struct eth_device *dev; |
||||
|
||||
dev = eth_get_dev_by_name(devname); |
||||
if (dev) |
||||
eth_mdio_read(dev, addr, reg, val); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
static int dw_mii_write(char *devname, u8 addr, u8 reg, u16 val) |
||||
{ |
||||
struct eth_device *dev; |
||||
|
||||
dev = eth_get_dev_by_name(devname); |
||||
if (dev) |
||||
eth_mdio_write(dev, addr, reg, val); |
||||
|
||||
return 0; |
||||
} |
||||
#endif |
||||
|
||||
int designware_initialize(u32 id, ulong base_addr, u32 phy_addr) |
||||
{ |
||||
struct eth_device *dev; |
||||
struct dw_eth_dev *priv; |
||||
|
||||
dev = (struct eth_device *) malloc(sizeof(struct eth_device)); |
||||
if (!dev) |
||||
return -ENOMEM; |
||||
|
||||
/*
|
||||
* Since the priv structure contains the descriptors which need a strict |
||||
* buswidth alignment, memalign is used to allocate memory |
||||
*/ |
||||
priv = (struct dw_eth_dev *) memalign(16, sizeof(struct dw_eth_dev)); |
||||
if (!priv) { |
||||
free(dev); |
||||
return -ENOMEM; |
||||
} |
||||
|
||||
memset(dev, 0, sizeof(struct eth_device)); |
||||
memset(priv, 0, sizeof(struct dw_eth_dev)); |
||||
|
||||
sprintf(dev->name, "mii%d", id); |
||||
dev->iobase = (int)base_addr; |
||||
dev->priv = priv; |
||||
|
||||
eth_getenv_enetaddr_by_index(id, &dev->enetaddr[0]); |
||||
|
||||
priv->dev = dev; |
||||
priv->mac_regs_p = (struct eth_mac_regs *)base_addr; |
||||
priv->dma_regs_p = (struct eth_dma_regs *)(base_addr + |
||||
DW_DMA_BASE_OFFSET); |
||||
priv->address = phy_addr; |
||||
|
||||
if (mac_reset(dev) < 0) |
||||
return -1; |
||||
|
||||
if (configure_phy(dev) < 0) { |
||||
printf("Phy could not be configured\n"); |
||||
return -1; |
||||
} |
||||
|
||||
dev->init = dw_eth_init; |
||||
dev->send = dw_eth_send; |
||||
dev->recv = dw_eth_recv; |
||||
dev->halt = dw_eth_halt; |
||||
dev->write_hwaddr = dw_write_hwaddr; |
||||
|
||||
eth_register(dev); |
||||
|
||||
#if defined(CONFIG_MII) |
||||
miiphy_register(dev->name, dw_mii_read, dw_mii_write); |
||||
#endif |
||||
return 1; |
||||
} |
@ -0,0 +1,264 @@ |
||||
/*
|
||||
* (C) Copyright 2010 |
||||
* Vipin Kumar, ST Micoelectronics, vipin.kumar@st.com. |
||||
* |
||||
* See file CREDITS for list of people who contributed to this |
||||
* project. |
||||
* |
||||
* This program is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU General Public License as |
||||
* published by the Free Software Foundation; either version 2 of |
||||
* the License, or (at your option) any later version. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU General Public License |
||||
* along with this program; if not, write to the Free Software |
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, |
||||
* MA 02111-1307 USA |
||||
*/ |
||||
|
||||
#ifndef _DW_ETH_H |
||||
#define _DW_ETH_H |
||||
|
||||
#define CONFIG_TX_DESCR_NUM 16 |
||||
#define CONFIG_RX_DESCR_NUM 16 |
||||
#define CONFIG_ETH_BUFSIZE 2048 |
||||
#define TX_TOTAL_BUFSIZE (CONFIG_ETH_BUFSIZE * CONFIG_TX_DESCR_NUM) |
||||
#define RX_TOTAL_BUFSIZE (CONFIG_ETH_BUFSIZE * CONFIG_RX_DESCR_NUM) |
||||
|
||||
#define CONFIG_MACRESET_TIMEOUT (3 * CONFIG_SYS_HZ) |
||||
#define CONFIG_MDIO_TIMEOUT (3 * CONFIG_SYS_HZ) |
||||
#define CONFIG_PHYRESET_TIMEOUT (3 * CONFIG_SYS_HZ) |
||||
#define CONFIG_AUTONEG_TIMEOUT (5 * CONFIG_SYS_HZ) |
||||
|
||||
struct eth_mac_regs { |
||||
u32 conf; /* 0x00 */ |
||||
u32 framefilt; /* 0x04 */ |
||||
u32 hashtablehigh; /* 0x08 */ |
||||
u32 hashtablelow; /* 0x0c */ |
||||
u32 miiaddr; /* 0x10 */ |
||||
u32 miidata; /* 0x14 */ |
||||
u32 flowcontrol; /* 0x18 */ |
||||
u32 vlantag; /* 0x1c */ |
||||
u32 version; /* 0x20 */ |
||||
u8 reserved_1[20]; |
||||
u32 intreg; /* 0x38 */ |
||||
u32 intmask; /* 0x3c */ |
||||
u32 macaddr0hi; /* 0x40 */ |
||||
u32 macaddr0lo; /* 0x44 */ |
||||
}; |
||||
|
||||
/* MAC configuration register definitions */ |
||||
#define FRAMEBURSTENABLE (1 << 21) |
||||
#define MII_PORTSELECT (1 << 15) |
||||
#define FES_100 (1 << 14) |
||||
#define DISABLERXOWN (1 << 13) |
||||
#define FULLDPLXMODE (1 << 11) |
||||
#define RXENABLE (1 << 2) |
||||
#define TXENABLE (1 << 3) |
||||
|
||||
/* MII address register definitions */ |
||||
#define MII_BUSY (1 << 0) |
||||
#define MII_WRITE (1 << 1) |
||||
#define MII_CLKRANGE_60_100M (0) |
||||
#define MII_CLKRANGE_100_150M (0x4) |
||||
#define MII_CLKRANGE_20_35M (0x8) |
||||
#define MII_CLKRANGE_35_60M (0xC) |
||||
#define MII_CLKRANGE_150_250M (0x10) |
||||
#define MII_CLKRANGE_250_300M (0x14) |
||||
|
||||
#define MIIADDRSHIFT (11) |
||||
#define MIIREGSHIFT (6) |
||||
#define MII_REGMSK (0x1F << 6) |
||||
#define MII_ADDRMSK (0x1F << 11) |
||||
|
||||
|
||||
struct eth_dma_regs { |
||||
u32 busmode; /* 0x00 */ |
||||
u32 txpolldemand; /* 0x04 */ |
||||
u32 rxpolldemand; /* 0x08 */ |
||||
u32 rxdesclistaddr; /* 0x0c */ |
||||
u32 txdesclistaddr; /* 0x10 */ |
||||
u32 status; /* 0x14 */ |
||||
u32 opmode; /* 0x18 */ |
||||
u32 intenable; /* 0x1c */ |
||||
u8 reserved[40]; |
||||
u32 currhosttxdesc; /* 0x48 */ |
||||
u32 currhostrxdesc; /* 0x4c */ |
||||
u32 currhosttxbuffaddr; /* 0x50 */ |
||||
u32 currhostrxbuffaddr; /* 0x54 */ |
||||
}; |
||||
|
||||
#define DW_DMA_BASE_OFFSET (0x1000) |
||||
|
||||
/* Bus mode register definitions */ |
||||
#define FIXEDBURST (1 << 16) |
||||
#define PRIORXTX_41 (3 << 14) |
||||
#define PRIORXTX_31 (2 << 14) |
||||
#define PRIORXTX_21 (1 << 14) |
||||
#define PRIORXTX_11 (0 << 14) |
||||
#define BURST_1 (1 << 8) |
||||
#define BURST_2 (2 << 8) |
||||
#define BURST_4 (4 << 8) |
||||
#define BURST_8 (8 << 8) |
||||
#define BURST_16 (16 << 8) |
||||
#define BURST_32 (32 << 8) |
||||
#define RXHIGHPRIO (1 << 1) |
||||
#define DMAMAC_SRST (1 << 0) |
||||
|
||||
/* Poll demand definitions */ |
||||
#define POLL_DATA (0xFFFFFFFF) |
||||
|
||||
/* Operation mode definitions */ |
||||
#define STOREFORWARD (1 << 21) |
||||
#define FLUSHTXFIFO (1 << 20) |
||||
#define TXSTART (1 << 13) |
||||
#define TXSECONDFRAME (1 << 2) |
||||
#define RXSTART (1 << 1) |
||||
|
||||
/* Descriptior related definitions */ |
||||
#define MAC_MAX_FRAME_SZ (2048) |
||||
|
||||
struct dmamacdescr { |
||||
u32 txrx_status; |
||||
u32 dmamac_cntl; |
||||
void *dmamac_addr; |
||||
struct dmamacdescr *dmamac_next; |
||||
}; |
||||
|
||||
/*
|
||||
* txrx_status definitions |
||||
*/ |
||||
|
||||
/* tx status bits definitions */ |
||||
#if defined(CONFIG_DW_ALTDESCRIPTOR) |
||||
|
||||
#define DESC_TXSTS_OWNBYDMA (1 << 31) |
||||
#define DESC_TXSTS_TXINT (1 << 30) |
||||
#define DESC_TXSTS_TXLAST (1 << 29) |
||||
#define DESC_TXSTS_TXFIRST (1 << 28) |
||||
#define DESC_TXSTS_TXCRCDIS (1 << 27) |
||||
|
||||
#define DESC_TXSTS_TXPADDIS (1 << 26) |
||||
#define DESC_TXSTS_TXCHECKINSCTRL (3 << 22) |
||||
#define DESC_TXSTS_TXRINGEND (1 << 21) |
||||
#define DESC_TXSTS_TXCHAIN (1 << 20) |
||||
#define DESC_TXSTS_MSK (0x1FFFF << 0) |
||||
|
||||
#else |
||||
|
||||
#define DESC_TXSTS_OWNBYDMA (1 << 31) |
||||
#define DESC_TXSTS_MSK (0x1FFFF << 0) |
||||
|
||||
#endif |
||||
|
||||
/* rx status bits definitions */ |
||||
#define DESC_RXSTS_OWNBYDMA (1 << 31) |
||||
#define DESC_RXSTS_DAFILTERFAIL (1 << 30) |
||||
#define DESC_RXSTS_FRMLENMSK (0x3FFF << 16) |
||||
#define DESC_RXSTS_FRMLENSHFT (16) |
||||
|
||||
#define DESC_RXSTS_ERROR (1 << 15) |
||||
#define DESC_RXSTS_RXTRUNCATED (1 << 14) |
||||
#define DESC_RXSTS_SAFILTERFAIL (1 << 13) |
||||
#define DESC_RXSTS_RXIPC_GIANTFRAME (1 << 12) |
||||
#define DESC_RXSTS_RXDAMAGED (1 << 11) |
||||
#define DESC_RXSTS_RXVLANTAG (1 << 10) |
||||
#define DESC_RXSTS_RXFIRST (1 << 9) |
||||
#define DESC_RXSTS_RXLAST (1 << 8) |
||||
#define DESC_RXSTS_RXIPC_GIANT (1 << 7) |
||||
#define DESC_RXSTS_RXCOLLISION (1 << 6) |
||||
#define DESC_RXSTS_RXFRAMEETHER (1 << 5) |
||||
#define DESC_RXSTS_RXWATCHDOG (1 << 4) |
||||
#define DESC_RXSTS_RXMIIERROR (1 << 3) |
||||
#define DESC_RXSTS_RXDRIBBLING (1 << 2) |
||||
#define DESC_RXSTS_RXCRC (1 << 1) |
||||
|
||||
/*
|
||||
* dmamac_cntl definitions |
||||
*/ |
||||
|
||||
/* tx control bits definitions */ |
||||
#if defined(CONFIG_DW_ALTDESCRIPTOR) |
||||
|
||||
#define DESC_TXCTRL_SIZE1MASK (0x1FFF << 0) |
||||
#define DESC_TXCTRL_SIZE1SHFT (0) |
||||
#define DESC_TXCTRL_SIZE2MASK (0x1FFF << 16) |
||||
#define DESC_TXCTRL_SIZE2SHFT (16) |
||||
|
||||
#else |
||||
|
||||
#define DESC_TXCTRL_TXINT (1 << 31) |
||||
#define DESC_TXCTRL_TXLAST (1 << 30) |
||||
#define DESC_TXCTRL_TXFIRST (1 << 29) |
||||
#define DESC_TXCTRL_TXCHECKINSCTRL (3 << 27) |
||||
#define DESC_TXCTRL_TXCRCDIS (1 << 26) |
||||
#define DESC_TXCTRL_TXRINGEND (1 << 25) |
||||
#define DESC_TXCTRL_TXCHAIN (1 << 24) |
||||
|
||||
#define DESC_TXCTRL_SIZE1MASK (0x7FF << 0) |
||||
#define DESC_TXCTRL_SIZE1SHFT (0) |
||||
#define DESC_TXCTRL_SIZE2MASK (0x7FF << 11) |
||||
#define DESC_TXCTRL_SIZE2SHFT (11) |
||||
|
||||
#endif |
||||
|
||||
/* rx control bits definitions */ |
||||
#if defined(CONFIG_DW_ALTDESCRIPTOR) |
||||
|
||||
#define DESC_RXCTRL_RXINTDIS (1 << 31) |
||||
#define DESC_RXCTRL_RXRINGEND (1 << 15) |
||||
#define DESC_RXCTRL_RXCHAIN (1 << 14) |
||||
|
||||
#define DESC_RXCTRL_SIZE1MASK (0x1FFF << 0) |
||||
#define DESC_RXCTRL_SIZE1SHFT (0) |
||||
#define DESC_RXCTRL_SIZE2MASK (0x1FFF << 16) |
||||
#define DESC_RXCTRL_SIZE2SHFT (16) |
||||
|
||||
#else |
||||
|
||||
#define DESC_RXCTRL_RXINTDIS (1 << 31) |
||||
#define DESC_RXCTRL_RXRINGEND (1 << 25) |
||||
#define DESC_RXCTRL_RXCHAIN (1 << 24) |
||||
|
||||
#define DESC_RXCTRL_SIZE1MASK (0x7FF << 0) |
||||
#define DESC_RXCTRL_SIZE1SHFT (0) |
||||
#define DESC_RXCTRL_SIZE2MASK (0x7FF << 11) |
||||
#define DESC_RXCTRL_SIZE2SHFT (11) |
||||
|
||||
#endif |
||||
|
||||
struct dw_eth_dev { |
||||
u32 address; |
||||
u32 speed; |
||||
u32 duplex; |
||||
u32 tx_currdescnum; |
||||
u32 rx_currdescnum; |
||||
u32 padding; |
||||
|
||||
struct dmamacdescr tx_mac_descrtable[CONFIG_TX_DESCR_NUM]; |
||||
struct dmamacdescr rx_mac_descrtable[CONFIG_RX_DESCR_NUM]; |
||||
|
||||
char txbuffs[TX_TOTAL_BUFSIZE]; |
||||
char rxbuffs[RX_TOTAL_BUFSIZE]; |
||||
|
||||
struct eth_mac_regs *mac_regs_p; |
||||
struct eth_dma_regs *dma_regs_p; |
||||
|
||||
struct eth_device *dev; |
||||
} __attribute__ ((aligned(8))); |
||||
|
||||
/* Speed specific definitions */ |
||||
#define SPEED_10M 1 |
||||
#define SPEED_100M 2 |
||||
#define SPEED_1000M 3 |
||||
|
||||
/* Duplex mode specific definitions */ |
||||
#define HALF_DUPLEX 1 |
||||
#define FULL_DUPLEX 2 |
||||
|
||||
#endif |
Loading…
Reference in new issue