net: sh: Renesas SH7763 Ethernet device support
PATCH 1/1 net: sh: Renesas SH7763 Ethernet device support
Renesas SH7763 has 2 channel Ethernet device. This is 10/100/1000 Base support.
But this patch check 10/100 Base only.
--- 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
drivers/net/Makefile +1 -0
@@ -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)
drivers/net/sh_eth.c new file +599 -0
599 lines not on this page · raw message
drivers/net/sh_eth.h new file +195 -0
195 lines not on this page · raw message
Signature · 1 line
1.5.5.1
PATCH 1/1 net: sh: Renesas SH7763 Ethernet device support
Hello, Ben.
Quoted 4 lines · On Fri, 06 Jun 2008 16:17:48 +0900 Nobuhiro Iwamatsu…
Renesas SH7763 has 2 channel Ethernet device.
This is 10/100/1000 Base support.
But this patch check 10/100 Base only.
Quoted 9 lines
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
Please apply this code to your net tree?
Best regards,
Nobuhiro
Signature · 1 line
Nobuhiro Iwamatsu
PATCH 1/1 net: sh: Renesas SH7763 Ethernet device support
Hi Nobuhiro,
Quoted 21 lines · Nobuhiro Iwamatsu
Hello, Ben.
Quoted 4 lines · On Fri, 06 Jun 2008 16:17:48 +0900 Nobuhiro Iwamatsu…
Renesas SH7763 has 2 channel Ethernet device.
This is 10/100/1000 Base support.
But this patch check 10/100 Base only.Quoted 10 lines
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
Quoted 3 lines
Please apply this code to your net tree?
I've scanned over the code and plan to give it a more thorough review tonight.
regards,
Ben
PATCH 1/1 net: sh: Renesas SH7763 Ethernet device support
In reply to Nobuhiro IwamatsuHi Nobuhiro,
Quoted 10 lines · Nobuhiro Iwamatsu
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?
Quoted 452 lines
3 files changed, 795 insertions(+), 0 deletions(-) create mode 100644 drivers/net/sh_eth.c create mode 100644 drivers/net/sh_eth.hdrivers/net/Makefile +1
-0@@ -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)drivers/net/sh_eth.c new file +429
-0@@ -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 ; +}
drivers/net/sh_eth.c line 439
Quoted 10 lines
drivers/net/sh_eth.c new file +10
-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.
Quoted 14 lines
drivers/net/sh_eth.c new file +13
-0+ 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 */
drivers/net/sh_eth.c line 462
Quoted 10 lines
drivers/net/sh_eth.c new file +10
-0+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
Quoted 269 lines
drivers/net/sh_eth.c new file +137
-0+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; + +}drivers/net/sh_eth.h new file +125
-0@@ -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; +}; +
drivers/net/sh_eth.h line 135
Quoted 10 lines
drivers/net/sh_eth.h new file +10
-0+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.
Quoted 51 lines
drivers/net/sh_eth.h new file +50
-0+#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) +
drivers/net/sh_eth.h line 195
Quoted 10 lines
drivers/net/sh_eth.h new file +10
-0+/* 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
PATCH 1/1 net: sh: Renesas SH7763 Ethernet device support
Hi, Ben.
Thank you for your check.
2008/6/10 Ben Warren <[email protected]>:
Quoted 8 lines
Hi Nobuhiro,
Quoted 3 lines · Nobuhiro Iwamatsu
Renesas SH7763 has 2 channel Ethernet device. This is 10/100/1000 Base support.
But this patch check 10/100 Base only.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?
Yes , this driver initialize used eth_init. Thank you.
<snip>
Quoted 2 lines
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.
<snip>
Quoted 1 line
Another magic number that should be a #defined bit mask
Thanks. I will rewrite and cleanup soruce code.
<snip>
Quoted 6 lines
Quoted 6 lines
drivers/net/sh_eth.h new file +0
-0@@ -0,0 +1,195 @@
<snip>
Quoted 2 lines
Please use the accessors in
include/asm-sh/io.hinstead of defining your own.
OK.
I revise the place that you pointed out and resend it. I thank for your check.
Best regards,
Nobuhiro