Renesas SH7763 has 2 channel Ethernet device. This is 10/100/1000 Base support. But this patch check 10/100 Base only.
Signed-off-by: Nobuhiro Iwamatsu <[EMAIL PROTECTED]> --- drivers/net/Makefile | 1 + drivers/net/sh_eth.c | 599 ++++++++++++++++++++++++++++++++++++++++++++++++++ drivers/net/sh_eth.h | 195 ++++++++++++++++ 3 files changed, 795 insertions(+), 0 deletions(-) create mode 100644 drivers/net/sh_eth.c create mode 100644 drivers/net/sh_eth.h diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 5b031c9..e2a6b35 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -66,6 +66,7 @@ COBJS-y += uli526x.o COBJS-y += vsc7385.o COBJS-$(CONFIG_XILINX_EMAC) += xilinx_emac.o COBJS-$(CONFIG_XILINX_EMACLITE) += xilinx_emaclite.o +COBJS-$(CONFIG_SH_ETHER) += sh_eth.o COBJS := $(COBJS-y) SRCS := $(COBJS:.o=.c) diff --git a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c new file mode 100644 index 0000000..869a8f0 --- /dev/null +++ b/drivers/net/sh_eth.c @@ -0,0 +1,599 @@ +/* + * sh_eth.c - Driver for Renesas SH7763's ethernet controler. + * + * Copyright (C) 2008 Renesas Solutions Corp. + * Copyright (c) 2008 Nobuhiro Iwamatsu + * Copyright (c) 2007 Carlos Munoz <[EMAIL PROTECTED]> + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <config.h> +#include <common.h> +#include <malloc.h> +#include <net.h> +#include <asm/errno.h> + +#include "sh_eth.h" + +#ifndef CONFIG_SH_ETHER_USE_PORT +# error "Please define CONFIG_SH_ETHER_USE_PORT" +#endif +#ifndef CONFIG_SH_ETHER_PHY_ADDR +# error "Please define CONFIG_SH_ETHER_PHY_ADDR" +#endif + +extern int eth_init(bd_t *bd); +extern void eth_halt(void); +extern int eth_rx(void); +extern int eth_send(volatile void *packet, int length); + +static struct dev_info_s *dev; + +/* + * Bits are written to the PHY serially using the + * PIR register, just like a bit banger. + */ +static void sh_eth_mii_write_phy_bits(int port, u32 val, int len) +{ + int i; + u32 pir; + + /* Bit positions is 1 less than the number of bits */ + for (i = len - 1; i >= 0; i--) { + /* Write direction, bit to write, clock is low */ + pir = 2 | ((val & 1 << i) ? 1 << 2 : 0); + OUT32(PIR(port), pir); + PHY_DELAY; + /* Write direction, bit to write, clock is high */ + pir = 3 | ((val & 1 << i) ? 1 << 2 : 0); + OUT32(PIR(port), pir); + PHY_DELAY; + /* Write direction, bit to write, clock is low */ + pir = 2 | ((val & 1 << i) ? 1 << 2 : 0); + OUT32(PIR(port), pir); + PHY_DELAY; + } +} + +static void sh_eth_mii_bus_release(int port) +{ + /* Read direction, clock is low */ + OUT32(PIR(port), 0); + PHY_DELAY; + /* Read direction, clock is high */ + OUT32(PIR(port), 1); + PHY_DELAY; + /* Read direction, clock is low */ + OUT32(PIR(port), 0); + PHY_DELAY; +} + +static void sh_eth_mii_ind_bus_release(int port) +{ + /* Read direction, clock is low */ + OUT32(PIR(port), 0); + PHY_DELAY; +} + +static int sh_eth_mii_read_phy_bits(int port, u32 * val, int len) +{ + int i; + u32 pir; + + *val = 0; + for (i = len - 1; i >= 0; i--) { + /* Read direction, clock is high */ + OUT32(PIR(port), 1); + PHY_DELAY; + /* Read bit */ + pir = IN32(PIR(port)); + *val |= (pir & 8) ? 1 << i : 0; + /* Read direction, clock is low */ + OUT32(PIR(port), 0); + PHY_DELAY; + } + + return 0; +} + +/* To read a phy register, mii managements frames are sent to the phy. + The frames look like this: + pre (32 bits): 0xffff ffff + st (2 bits): 01 + op (2bits): 10: read 01: write + phyad (5 bits): xxxxx + regad (5 bits): xxxxx + ta (Bus release): + data (16 bits): read data */ +static u32 sh_eth_mii_read_phy_reg(int port, u8 phy_addr, int reg) +{ + u32 val; + + /* Sent mii management frame */ + /* pre */ + sh_eth_mii_write_phy_bits(port, 0xffffffff, 32); + /* st (start of frame) */ + sh_eth_mii_write_phy_bits(port, 0x1, 2); + /* op (code) */ + sh_eth_mii_write_phy_bits(port, 0x2, 2); + /* phy address */ + sh_eth_mii_write_phy_bits(port, phy_addr, 5); + /* Register to read */ + sh_eth_mii_write_phy_bits(port, reg, 5); + + /* Bus release */ + sh_eth_mii_bus_release(port); + + /* Read register */ + sh_eth_mii_read_phy_bits(port, &val, 16); + + return val; +} + +/* To write a phy register, mii managements frames are sent to the phy. + The frames look like this: + pre (32 bits): 0xffff ffff + st (2 bits): 01 + op (2bits): 10: read 01: write + phyad (5 bits): xxxxx + regad (5 bits): xxxxx + ta (2 bits): 10 + data (16 bits): write data + idle (Independent bus release) */ +static void sh_eth_mii_write_phy_reg(int port, u8 phy_addr, int reg, u16 val) +{ + /* Sent mii management frame */ + /* pre */ + sh_eth_mii_write_phy_bits(port, 0xffffffff, 32); + /* st (start of frame) */ + sh_eth_mii_write_phy_bits(port, 0x1, 2); + /* op (code) */ + sh_eth_mii_write_phy_bits(port, 0x1, 2); + /* phy address */ + sh_eth_mii_write_phy_bits(port, phy_addr, 5); + /* Register to read */ + sh_eth_mii_write_phy_bits(port, reg, 5); + /* ta */ + sh_eth_mii_write_phy_bits(port, 0x2, 2); + /* Write register data */ + sh_eth_mii_write_phy_bits(port, val, 16); + + /* Independent bus release */ + sh_eth_mii_ind_bus_release(port); +} + +void eth_halt(void) +{ +} + +int eth_send(volatile void *packet, int len) +{ + int port = dev->port; + struct port_info_s *port_info = &dev->port_info[port]; + int timeout; + int rc = 0; + + if (!packet || len > 0xffff) { + printf("eth_send: Invalid argument\n"); + return -EINVAL; + } + + /* packet must be a 4 byte boundary */ + if ((int)packet & (4 - 1)) { + printf("eth_send: packet not 4 byte alligned\n"); + return -EFAULT; + } + + /* Update tx descriptor */ + port_info->tx_desc_cur->td2 = ADDR_TO_PHY(packet); + port_info->tx_desc_cur->td1 = len << 16; + /* Must preserve the end of descriptor list indication */ + if (port_info->tx_desc_cur->td0 & TDLE) + port_info->tx_desc_cur->td0 = TACT | TFP | TDLE; + else + port_info->tx_desc_cur->td0 = TACT | TFP; + + /* Restart the transmitter if disabled */ + if (!(IN32(EDTRR(port)) & 0x3)) + OUT32(EDTRR(port), 0x3); + + /* Wait until packet is transmitted */ + timeout = 1000; + while (port_info->tx_desc_cur->td0 & TACT && timeout--) + udelay(100); + + if (timeout < 0) { + printf("eth_send: transmit timeout\n"); + rc = -1; + goto err; + } + + err: + port_info->tx_desc_cur++; + if (port_info->tx_desc_cur >= port_info->tx_desc_base + NUM_TX_DESC) + port_info->tx_desc_cur = port_info->tx_desc_base; + + return rc; +} + +int eth_rx(void) +{ + int port = dev->port; + struct port_info_s *port_info = &dev->port_info[port]; + int len = 0; + volatile u8 *packet; + + /* Check if the rx descriptor is ready */ + if (!(port_info->rx_desc_cur->rd0 & RACT)) { + /* Check for errors */ + if (!(port_info->rx_desc_cur->rd0 & RFE)) { + len = port_info->rx_desc_cur->rd1 & 0xffff; + packet = (volatile u8 *) + ADDR_TO_P2(port_info->rx_desc_cur->rd2); + NetReceive(packet, len); + } + + /* Make current descriptor available again */ + if (port_info->rx_desc_cur->rd0 & RDLE) + port_info->rx_desc_cur->rd0 = RACT | RDLE; + else + port_info->rx_desc_cur->rd0 = RACT; + + /* Point to the next descriptor */ + port_info->rx_desc_cur++; + if (port_info->rx_desc_cur >= + port_info->rx_desc_base + NUM_RX_DESC) + port_info->rx_desc_cur = port_info->rx_desc_base; + } + + /* Restart the receiver if disabled */ + if (!(IN32(EDRRR(port)) & 0x1)) + OUT32(EDRRR(port), 0x1); + + return len; +} + +static int sh_eth_reset(struct dev_info_s *dev) +{ + int port = dev->port; + int i; + + /* Start e-dmac transmitter and receiver */ + OUT32(EDSR(port), 0x3); + + /* Perform a software reset and wait for it to complete */ + OUT32(EDMR(port), 0x3); + for (i = 0; i < 1000; i++) { + if (!(IN32(EDMR(port)) & 0x3)) + break; + + udelay(1000); + } + + if (i == 100) { + printf("Error: Software reset timeout\n"); + return -1; + } + + return 0; +} + +static int sh_eth_tx_desc_init(struct dev_info_s *dev) +{ + int port = dev->port; + struct port_info_s *port_info = &dev->port_info[port]; + u32 tmp_addr; + struct tx_desc_s *cur_tx_desc; + int i; + + /* Allocate tx descriptors. They must be TX_DESC_SIZE bytes + aligned */ + if (!(port_info->tx_desc_malloc = malloc(NUM_TX_DESC * + sizeof(struct tx_desc_s) + + TX_DESC_SIZE - 1))) { + printf("Error: malloc failed\n"); + return -ENOMEM; + } + tmp_addr = (u32) (((int)port_info->tx_desc_malloc + TX_DESC_SIZE - 1) & + ~(TX_DESC_SIZE - 1)); + /* Make sure we use a P2 address (non-cacheable) */ + port_info->tx_desc_base = (struct tx_desc_s *)ADDR_TO_P2(tmp_addr); + + port_info->tx_desc_cur = port_info->tx_desc_base; + + /* Initialize all descriptors */ + for (cur_tx_desc = port_info->tx_desc_base, i = 0; i < NUM_TX_DESC; + cur_tx_desc++, i++) { + cur_tx_desc->td0 = 0; + cur_tx_desc->td1 = 0; + cur_tx_desc->td2 = 0; + } + + /* Mark the end of the descriptors */ + cur_tx_desc--; + cur_tx_desc->td0 |= TDLE; + + /* Point the controller to the tx descriptor list. Must use physical + addresses */ + OUT32(TDLAR(port), ADDR_TO_PHY(port_info->tx_desc_base)); + OUT32(TDFAR(port), ADDR_TO_PHY(port_info->tx_desc_base)); + OUT32(TDFXR(port), ADDR_TO_PHY(cur_tx_desc)); + OUT32(TDFFR(port), 0x0000001); + + return 0; +} + +static int sh_eth_rx_desc_init(struct dev_info_s *dev) +{ + int port = dev->port; + struct port_info_s *port_info = &dev->port_info[port]; + u32 tmp_addr; + struct rx_desc_s *cur_rx_desc; + u8 *rx_buf; + int i; + + /* Allocate rx descriptors. They must be RX_DESC_SIZE bytes + aligned */ + if (!(port_info->rx_desc_malloc = malloc(NUM_RX_DESC * + sizeof(struct rx_desc_s) + + RX_DESC_SIZE - 1))) { + printf("Error: malloc failed\n"); + return -ENOMEM; + } + tmp_addr = (u32) (((int)port_info->rx_desc_malloc + RX_DESC_SIZE - 1) & + ~(RX_DESC_SIZE - 1)); + /* Make sure we use a P2 address (non-cacheable) */ + port_info->rx_desc_base = (struct rx_desc_s *)ADDR_TO_P2(tmp_addr); + + port_info->rx_desc_cur = port_info->rx_desc_base; + + /* Allocate rx data buffers. They must be 32 bytes aligned and in + P2 area */ + if (!(port_info->rx_buf_malloc = malloc(NUM_RX_DESC * MAX_BUF_SIZE + + 31))) { + printf("Error: malloc failed\n"); + free(port_info->rx_desc_malloc); + port_info->rx_desc_malloc = NULL; + return -ENOMEM; + } + tmp_addr = (u32) (((int)port_info->rx_buf_malloc + (32 - 1)) & + ~(32 - 1)); + port_info->rx_buf_base = (u8 *) ADDR_TO_P2(tmp_addr); + + /* Initialize all descriptors */ + for (cur_rx_desc = port_info->rx_desc_base, + rx_buf = port_info->rx_buf_base, i = 0; + i < NUM_RX_DESC; cur_rx_desc++, rx_buf += MAX_BUF_SIZE, i++) { + cur_rx_desc->rd0 = RACT; + cur_rx_desc->rd1 = MAX_BUF_SIZE << 16; + cur_rx_desc->rd2 = (u32) ADDR_TO_PHY(rx_buf); + } + + /* Mark the end of the descriptors */ + cur_rx_desc--; + cur_rx_desc->rd0 |= RDLE; + + /* Point the controller to the rx descriptor list */ + OUT32(RDLAR(port), ADDR_TO_PHY(port_info->rx_desc_base)); + OUT32(RDFAR(port), ADDR_TO_PHY(port_info->rx_desc_base)); + OUT32(RDFXR(port), ADDR_TO_PHY(cur_rx_desc)); + OUT32(RDFFR(port), 0x00000001); + + return 0; +} + +static void sh_eth_desc_free(struct dev_info_s *dev) +{ + int port = dev->port; + struct port_info_s *port_info = &dev->port_info[port]; + + if (port_info->tx_desc_malloc) { + free(port_info->tx_desc_malloc); + port_info->tx_desc_malloc = NULL; + } + + if (port_info->rx_desc_malloc) { + free(port_info->rx_desc_malloc); + port_info->rx_desc_malloc = NULL; + } + + if (port_info->rx_buf_malloc) { + free(port_info->rx_buf_malloc); + port_info->rx_buf_malloc = NULL; + } +} + +static int sh_eth_desc_init(struct dev_info_s *dev) +{ + int rc; + + if ((rc = sh_eth_tx_desc_init(dev)) || (rc = sh_eth_rx_desc_init(dev))) { + sh_eth_desc_free(dev); + return rc; + } + + return 0; +} + +static int sh_eth_phy_config(struct dev_info_s *dev) +{ + int port = dev->port; + struct port_info_s *port_info = &dev->port_info[port]; + int timeout; + u32 val; + + /* Reset phy */ + sh_eth_mii_write_phy_reg(port, port_info->phy_addr, 0, 0x8000); + timeout = 10; + while (timeout--) { + val = sh_eth_mii_read_phy_reg(port, port_info->phy_addr, 0); + if (!(val & 0x8000)) + break; + udelay(50000); + } + if (timeout < 0) { + printf("sh_eth_phy_config() phy reset timeout\n"); + return -1; + } + + /* Advertise 100/10 baseT full/half duplex */ + sh_eth_mii_write_phy_reg(port, port_info->phy_addr, 4, 0x01e1); + + /* Autonegotiation, normal operation, full duplex, enable tx */ + sh_eth_mii_write_phy_reg(port, port_info->phy_addr, 0, 0x1200); + + /* Wait for autonegotiation to complete */ + timeout = 100; + while (timeout--) { + val = sh_eth_mii_read_phy_reg(port, port_info->phy_addr, 1); + if (val & 0x0020) + break; + udelay(50000); + } + if (timeout < 0) { + printf("sh_eth_phy_config() phy auto-negotiation failed\n"); + return -1; + } + + return 0; +} + +static int sh_eth_config(struct dev_info_s *dev, bd_t * bd) +{ + int port = dev->port; + struct port_info_s *port_info = &dev->port_info[port]; + u32 val; + u32 phy_status; + int rc; + + /* Configure e-dmac registers */ + OUT32(EDMR(port), (IN32(EDMR(port)) & ~0x00000030) | 0x00000040); + OUT32(EESIPR(port), 0); + OUT32(TRSCER(port), 0); + OUT32(TFTR(port), 0); + OUT32(FDR(port), 0x0000071f); + OUT32(RMCR(port), 1); + OUT32(RPADIR(port), 0); + OUT32(FCFTR(port), 0x00170007); + + /* Configure e-mac registers */ + OUT32(ECSIPR(port), 0); + + val = bd->bi_enetaddr[0] << 24 | bd->bi_enetaddr[1] << 16 | + bd->bi_enetaddr[2] << 8 | bd->bi_enetaddr[3]; + OUT32(MAHR(port), val); + + val = bd->bi_enetaddr[4] << 8 | bd->bi_enetaddr[5]; + OUT32(MALR(port), val); + + OUT32(RFLR(port), 0x000005ee); + OUT32(PIPR(port), 0); + OUT32(APR(port), 4); + OUT32(MPR(port), 6); + OUT32(TPAUSER(port), 6); + + /* Configure phy */ + if ((rc = sh_eth_phy_config(dev))) + return rc; + + /* Read phy status to finish configuring the e-mac */ + phy_status = sh_eth_mii_read_phy_reg(dev->port, + dev->port_info[dev->port].phy_addr, + 1); + + /* Set the transfer speed */ + if (phy_status & 0x6000) { + printf("100Base/"); + OUT32(GECMR(port), 0x4); + } else { + printf("10Base/"); + OUT32(GECMR(port), 0x0); + } + /* Check if full duplex mode is supported by the phy */ + if (phy_status & 0x5000) { + printf("Full\n"); + OUT32(ECMR(port), 0x041f2062); + } else { + printf("Half\n"); + OUT32(ECMR(port), 0x041f2060); + } + return 0; +} + +static int sh_eth_start(struct dev_info_s *dev) +{ + int port = dev->port; + + /* + * Enable the e-dmac receiver only. The transmitter will be enabled when + * we have something to transmit + */ + OUT32(EDRRR(port), 0x1); + + return 0; +} + +static int sh_eth_get_mac(bd_t *bd) +{ + char *s, *e; + int i; + + s = getenv("ethaddr"); + if (s != NULL) { + for (i = 0; i < 6; ++i) { + bd->bi_enetaddr[i] = s ? simple_strtoul(s, &e, 16) : 0; + if (s) + s = (*e) ? e + 1 : e; + } + } else { + puts("Please set MAC address\n"); + } + return 0; +} + +int eth_init(bd_t * bd) +{ + int rc; + + /* Allocate main device information structure */ + if (!(dev = malloc(sizeof(*dev)))) { + printf("eth_init: malloc failed\n"); + return -ENOMEM; + } + + memset(dev, 0, sizeof(*dev)); + + dev->port = CONFIG_SH_ETHER_USE_PORT; + dev->port_info[dev->port].phy_addr = CONFIG_SH_ETHER_PHY_ADDR; + + sh_eth_get_mac(bd); + + if ((rc = sh_eth_reset(dev)) || (rc = sh_eth_desc_init(dev))) + goto err; + + if ((rc = sh_eth_config(dev, bd)) || (rc = sh_eth_start(dev))) + goto err_desc; + + return 0; + +err_desc: + sh_eth_desc_free(dev); +err: + free(dev); + printf("eth_init: Failed\n"); + return rc; + +} diff --git a/drivers/net/sh_eth.h b/drivers/net/sh_eth.h new file mode 100644 index 0000000..12a4528 --- /dev/null +++ b/drivers/net/sh_eth.h @@ -0,0 +1,195 @@ +/* + * gether.h - Driver for Renesas SH7763's gigabit ethernet controler. + * + * Copyright (c) 2007 Carlos Munoz <[EMAIL PROTECTED]> + * Copyright (c) 2008 Nobuhiro Iwamatsu + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <asm/types.h> + +#define SHETHER_NAME "sh_eth" + +/* Malloc returns addresses in the P1 area (cacheable). However we need to + use area P2 (non-cacheable) */ +#define ADDR_TO_P2(addr) ((((int)(addr) & ~0xe0000000) | 0xa0000000)) + +/* The ethernet controller needs to use physical addresses */ +#define ADDR_TO_PHY(addr) ((int)(addr) & ~0xe0000000) + +/* Number of supported ports */ +#define MAX_PORT_NUM 2 + +/* Buffers must be big enough to hold the largest ethernet frame. Also, rx + buffers must be a multiple of 32 bytes */ +#define MAX_BUF_SIZE (48 * 32) + +/* The number of tx descriptors must be large enough to point to 5 or more + frames. If each frame uses 2 descriptors, at least 10 descriptors are needed. + We use one descriptor per frame */ +#define NUM_TX_DESC 8 + +/* The size of the tx descriptor is determined by how much padding is used. + 4, 20, or 52 bytes of padding can be used */ +#define TX_DESC_PADDING 4 +#define TX_DESC_SIZE (12 + TX_DESC_PADDING) + +/* Tx descriptor. We always use 4 bytes of padding */ +struct tx_desc_s { + volatile u32 td0; + u32 td1; + u32 td2; /* Buffer start */ + u32 padding; +}; + +/* TD0 */ +#define TACT (0x1 << 31) /* Valid/invalid */ +#define TDLE (0x1 << 30) /* List end */ +#define TFP (0x3 << 28) /* Frame position */ +#define TFP_END (0x1 << 28) /* End of frame */ +#define TFP_START (0x2 << 28) /* Start of frame */ +#define TFE (0x1 << 27) /* Error occurrence */ +#define TWBI (0x1 << 26) /* Write-back completion int */ +#define TFS (0xfff << 0) /* Frame status */ +#define TFS_UNFLW (0x1 << 9) /* Underflow */ +#define TFS_ABORT (0x1 << 8) /* Abort */ + +/* TD1 */ +#define TDL (0xffff << 16) /* Buffer data length */ + +/* There is no limitation in the number of rx descriptors */ +#define NUM_RX_DESC 8 + +/* The size of the rx descriptor is determined by how much padding is used. + 4, 20, or 52 bytes of padding can be used */ +#define RX_DESC_PADDING 4 +#define RX_DESC_SIZE (12 + RX_DESC_PADDING) + +/* Rx descriptor. We always use 4 bytes of padding */ +struct rx_desc_s { + volatile u32 rd0; + volatile u32 rd1; + u32 rd2; /* Buffer start */ + u32 padding; +}; + +/* RD0 */ +#define RACT (0x1 << 31) /* Valid/invalid */ +#define RDLE (0x1 << 30) /* List end */ +#define RFP (0x3 << 28) /* Frame position */ +#define RFP_END (0x1 << 28) /* End of frame */ +#define RFP_START (0x2 << 28) /* Start of frame */ +#define RFE (0x1 << 27) /* Error occurrence */ +#define PV (0x1 << 26) /* Padding Insertion */ +#define RFS (0xfff << 0) /* Frame status */ +#define RFS_OVFLW (0x1 << 9) /* Overflow */ +#define RFS_ABORT (0x1 << 8) /* Abort */ +#define RFS_MCAST (0x1 << 7) /* Multicast Address */ +#define RFS_CEXT (0x1 << 6) /* Carrier ext error */ +#define RFS_CELOSS (0x1 << 5) /* Carrier ext loss */ +#define RFS_RBF (0x1 << 4) /* Residual-bit frame error */ +#define RFS_LONG (0x1 << 3) /* Long frame */ +#define RFS_SHORT (0x1 << 2) /* Short frame */ +#define RFS_PHY (0x1 << 1) /* PHY rx error */ +#define RFS_CRC (0x1 << 0) /* CRC error */ + +/* RD1 */ +#define RBL (0xffff << 16) /* Buffer length */ +#define RDL (0xffff << 0) /* Buffer data length */ + +struct port_info_s { + struct tx_desc_s *tx_desc_malloc; + struct tx_desc_s *tx_desc_base; + struct tx_desc_s *tx_desc_cur; + struct rx_desc_s *rx_desc_malloc; + struct rx_desc_s *rx_desc_base; + struct rx_desc_s *rx_desc_cur; + u8 *rx_buf_malloc; + u8 *rx_buf_base; + u8 mac_addr[6]; + u8 phy_addr; +}; + +struct dev_info_s { + int port; + struct port_info_s port_info[MAX_PORT_NUM]; +}; + +#define IN16(reg) (*(u16 *)(reg)) +#define IN32(reg) (*(u32 *)(reg)) +#define OUT16(reg, val) (*(u16 *)(reg) = (val)) +#define OUT32(reg, val) (*(u32 *)(reg) = (val)) + +#define PDCR 0xffef0006 +#define PECR 0xffef0008 +#define PFCR 0xffef000a +#define PGCR 0xffef000c +#define PHCR 0xffef000e +#define PJCR 0xffef0012 +#define PKCR 0xffef0014 +#define PLCR 0xffef0016 +#define PMCR 0xffef0018 +#define PSEL1 0xffef0072 +#define PSEL2 0xffef0074 +#define PSEL3 0xffef0076 + +#define BASE_IO_ADDR 0xfee00000 + +#define EDSR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x0000) + +#define TDLAR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x0010) +#define TDFAR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x0014) +#define TDFXR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x0018) +#define TDFFR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x001c) + +#define RDLAR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x0030) +#define RDFAR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x0034) +#define RDFXR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x0038) +#define RDFFR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x003c) + +#define EDMR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x0400) +#define EDTRR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x0408) +#define EDRRR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x0410) +#define EESR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x0428) +#define EESIPR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x0430) +#define TRSCER(port) (BASE_IO_ADDR + 0x800 * (port) + 0x0438) +#define TFTR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x0448) +#define FDR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x0450) +#define RMCR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x0458) +#define RPADIR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x0460) +#define FCFTR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x0468) +#define ECMR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x0500) +#define RFLR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x0508) +#define ECSIPR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x0518) +#define PIR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x0520) +#define PIPR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x052c) +#define APR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x0554) +#define MPR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x0558) +#define TPAUSER(port) (BASE_IO_ADDR + 0x800 * (port) + 0x0564) +#define GECMR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x05b0) +#define MALR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x05c8) +#define MAHR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x05c0) + +/* Bit values for EESR */ +#define EESR_CERF (0x1 << 0) +#define EESR_PRE (0x1 << 1) +#define EESR_RTSF (0x1 << 2) +#define EESR_RTLF (0x1 << 3) +#define EESR_RFOF (0x1 << 16) +#define EESR_FR (1 << 18) + +/* PHY values */ +#define PHY_DELAY udelay(1) -- 1.5.5.1 ------------------------------------------------------------------------- Check out the new SourceForge.net Marketplace. It's the best place to buy or sell services for just about anything Open Source. http://sourceforge.net/services/buy/index.php _______________________________________________ U-Boot-Users mailing list U-Boot-Users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/u-boot-users