Hi Nobuhiro, Nobuhiro Iwamatsu wrote: > 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 ++++++++++++++++ > Where's the code that has this driver being initialized by net/eth.c? Is it in another patch or should I just go to bed? > 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); > This code has quite a few magic numbers. Considering that you're submitting a header file too, it's hard to justify not adding mnemonics. > + 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) > Another magic number that should be a #defined bit mask > + 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)) > + > Please use the accessors in include/asm-sh/io.h instead of defining your own. > +#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) > As I already mentioned, please put more bit definitions here.
regards, Ben ------------------------------------------------------------------------- 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