DM9000 support for multiple interfaces
cover DM9000 support for multiple interfaces
This is a rework of the DM9000 driver to support registering interfaces dynamically (i.e. determine how many ethernet chips we have at boot and register 0, 1, 2, or more). It was tested on a yet-to-be-submitted board which is based on the PXA270 + 0, 1, or 2 DM9000 chips.
To maintain backwards compatibility with older board files, we add a new initialize function taking the io address, data address, and availability of a SROM chip. The old initialize function is now a shim around this new initialize function but provides the parameters based on the old DM9000 preprocessor symbols.
I have compile-tested this on all the arm-based boards.
Andrew Ruder (3):
dm9000: mark dump_regs() function as unused
dm9000: Add struct eth_device * to SROM functions
dm9000: rework dm9000 to support multiple devices
board/trizepsiv/eeprom.c | 5 +- drivers/net/dm9000x.c | 382 +++++++++++++++++++++++++++-------------------- include/dm9000.h | 8 +- include/netdev.h | 1 + 4 files changed, 224 insertions(+), 172 deletions(-)
Signature · 1 line
2.1.1
PATCH 1/3 dm9000: mark dump_regs() function as unused
dump_regs() is a handy function to keep around for bringing up a new dm9000-based board, but defining CONFIG_DM9000_DEBUG only adds the function - nowhere currently uses it. Rather than remove a potentially useful function, let's just tell gcc to not emit a warning when it is unused.
--- drivers/net/dm9000x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/dm9000x.c +1 -1
@@ -126,7 +126,7 @@ static void DM9000_iow(int reg, u8 value);#ifdef CONFIG_DM9000_DEBUG static void -dump_regs (void ) +dump_regs (void ) __attribute__ ((unused)) {DM9000_DBG ("\n" );DM9000_DBG ("NCR (0x00): %02x\n" ,DM9000_ior (0 ));
Signature · 1 line
2.1.1
PATCH 1/3 dm9000: mark dump_regs() function as unused
Quoted 17 lines · Andrew Ruder
dump_regs()is a handy function to keep around for bringing up a new dm9000-based board, but definingCONFIG_DM9000_DEBUGonly adds the function - nowhere currently uses it. Rather than remove a potentially useful function, let's just tell gcc to not emit a warning when it is unused.Signed-off-by Andrew Ruder <[email protected]>Cc Joe Hershberger <[email protected]>--- drivers/net/dm9000x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)drivers/net/dm9000x.c +0
-0
drivers/net/dm9000x.c static void DM9000_iow(int reg, u8 value); · line 132
Quoted 8 lines
drivers/net/dm9000x.c +1
-1@@ -126,7 +126,7 @@ static void DM9000_iow(int reg, u8 value);#ifdef CONFIG_DM9000_DEBUG static void -dump_regs (void ) +dump_regs (void ) __attribute__ ((unused)) {DM9000_DBG ("\n" );DM9000_DBG ("NCR (0x00): %02x\n" ,DM9000_ior (0 ));
Please make sure we have <linux/compiler.h> and use __unused (or __maybe_unused?) here, thanks!
Signature · 8 lines
Tom -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 836 bytes Desc: Digital signature URL: <http://lists.denx.de/pipermail/u-boot/attachments/20141020/df19f48d/attachment.pgp>
PATCH 2/3 dm9000: Add struct eth_device * to SROM functions
In reply to Andrew RuderCurrently this argument is not used. To eventually support multiple DM9000's these public-facing functions will need a new argument - the ethernet device. Fix-up the one board using this part of the DM9000 API. Compile-tested only.
--- board/trizepsiv/eeprom.c | 5 +++-- drivers/net/dm9000x.c | 10 +++++----- include/dm9000.h | 8 ++++---- 3 files changed, 12 insertions(+), 11 deletions(-)
board/trizepsiv/eeprom.c +3 -2
@@ -8,6 +8,7 @@#include <common.h> #include <command.h> #include <dm9000.h> +#include <net.h> static int do_read_dm9000_eeprom (cmd_tbl_t *cmdtp,int flag,int argc,char *const argv[]) {unsigned int i;
@@ -16,7 +17,7 @@ static int do_read_dm9000_eeprom ( cmd_tbl_t *cmdtp, int flag, int argc, char *for (i=0 ; i <0x40 ; i++) {if (!(i %0x10 ))printf ("\n%08x:" , i); -dm9000_read_srom_word (i, data); +dm9000_read_srom_word (eth_get_dev_by_index (0 ), i, data);printf (" %02x%02x" , data[1 ], data[0 ]); }printf ("\n" );
@@ -35,7 +36,7 @@ static int do_write_dm9000_eeprom ( cmd_tbl_t *cmdtp, int flag, int argc, char *printf ("Wrong offset : 0x%x\n" ,offset);return cmd_usage (cmdtp); } -dm9000_write_srom_word (offset, value); +dm9000_write_srom_word (eth_get_dev_by_index (0 ), offset, value);return (0 ); }
drivers/net/dm9000x.c +5 -5
@@ -534,9 +534,9 @@ static int dm9000_rx(struct eth_device *netdev)/* Read a word data from SROM */ -#if !defined(CONFIG_DM9000_NO_SROM ) -void dm9000_read_srom_word (int offset,u8 *to) +void dm9000_read_srom_word (struct eth_device *dev,int offset,u8 *to) { + (void )dev;DM9000_iow (DM9000_EPAR , offset);DM9000_iow (DM9000_EPCR ,0x4 );udelay (8000 );
@@ -545,8 +545,9 @@ void dm9000_read_srom_word(int offset, u8 *to) to[1 ] =DM9000_ior (DM9000_EPDRH ); } -void dm9000_write_srom_word (int offset,u16 val) +void dm9000_write_srom_word (struct eth_device *dev,int offset,u16 val) { + (void )dev;DM9000_iow (DM9000_EPAR , offset);DM9000_iow (DM9000_EPDRH , ((val >>8 ) &0xff ));DM9000_iow (DM9000_EPDRL , (val &0xff ));
@@ -554,14 +555,13 @@ void dm9000_write_srom_word(int offset, u16 val)udelay (8000 );DM9000_iow (DM9000_EPCR ,0 ); } -#endif static void dm9000_get_enetaddr (struct eth_device *dev) {#if !defined(CONFIG_DM9000_NO_SROM )int i;for (i =0 ; i <3 ; i++) -dm9000_read_srom_word (i, dev->enetaddr + (2 * i)); +dm9000_read_srom_word (dev, i, dev->enetaddr + (2 * i));#endif }
include/dm9000.h +4 -4
@@ -8,10 +8,10 @@#ifndef __DM9000_H__#define __DM9000_H__ +struct eth_device ; +/****************** function prototypes **********************/ -#if !defined(CONFIG_DM9000_NO_SROM ) -void dm9000_write_srom_word (int offset,u16 val); -void dm9000_read_srom_word (int offset,u8 *to); -#endif +void dm9000_write_srom_word (struct eth_device *dev,int offset,u16 val); +void dm9000_read_srom_word (struct eth_device *dev,int offset,u8 *to);#endif /* __DM9000_H__ */
Signature · 1 line
2.1.1
PATCH 2/3 dm9000: Add struct eth_device * to SROM functions
Hi Andrew,
Quoted 9 lines · Andrew Ruder
Currently this argument is not used. To eventually support multiple DM9000's these public-facing functions will need a new argument - the ethernet device. Fix-up the one board using this part of the DM9000 API. Compile-tested only.
Signed-off-by Andrew Ruder <[email protected]>Cc Joe Hershberger <[email protected]>Cc Stefano Babic <[email protected]>---
Best regards,
Stefano Babic
Signature · 5 lines
===================================================================== DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: +49-8142-66989-53 Fax: +49-8142-66989-80 Email: sbabic at denx.de =====================================================================
PATCH 2/3 dm9000: Add struct eth_device * to SROM functions
In reply to Andrew RuderQuoted 4 lines · Andrew Ruder
Currently this argument is not used. To eventually support multiple DM9000's these public-facing functions will need a new argument - the ethernet device. Fix-up the one board using this part of the DM9000 API. Compile-tested only.
[snip]
drivers/net/dm9000x.c static int dm9000_rx(struct eth_device *netdev) · line 539
Quoted 4 lines
drivers/net/dm9000x.c +2
-1-void dm9000_read_srom_word (int offset,u8 *to) +void dm9000_read_srom_word (struct eth_device *dev,int offset,u8 *to) { + (void )dev;
You shouldn't have to add this to avoid a warning I think. And frankly, if it does for some reason since 3/3 makes use of dev, I'm OK with a bisect adding a trivial warning like this, rather than do compiler games.
Signature · 8 lines
Tom -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 836 bytes Desc: Digital signature URL: <http://lists.denx.de/pipermail/u-boot/attachments/20141020/af3ddb84/attachment.pgp>
PATCH 2/3 dm9000: Add struct eth_device * to SROM functions
Quoted 4 lines · Tom Rini
You shouldn't have to add this to avoid a warning I think. And frankly, if it does for some reason since 3/3 makes use of dev, I'm OK with a bisect adding a trivial warning like this, rather than do compiler games.
Fair enough, the more I look at it, the more it looks like I probably missed a warning on this patch + CONFIG_DM9000_NO_SROM (defined but not used) so it is still pretty easy to trigger a warning on this patch. I'll just remove the indicated parts in v2 of the series and let the warnings get cleaned up in 3/3 as you have suggested.
Will send a v2 of series in a bit after seeing if there is any feedback on the approaches used in 3/3.
- Andy
PATCH 3/3 dm9000: rework dm9000 to support multiple devices
In reply to Andrew RuderThe DM9000 was hard-coded to only support one DM9000 device. This patch adds a new initialization function - dm9000_initialize_ex() - to support registering multiple (and possibly dynamic) numbers of dm9000 devices. This patch consists of:
* Change the board_info struct to a private struct under eth_device.
* Add io address/data address/srom availability information to this private struct.
* Replace all uses of DM9000_IO/DM9000_DATA with new members, ensure that the eth_device struct propagates down to all helper functions.
* Make dm9000_initialize() call dm9000_initialize_ex() with filled in information from the old preprocessor symbols (DM9000_IO, DM9000_DATA, etc.)
Overall the following parameters have been moved over to being a per-chip setting:
DM9000_IO, DM9000_DATA, CONFIG_DM9000_NO_SROM
while the following is still a global setting affecting all chips:
CONFIG_DM9000_BYTE_SWAPPED
And the following has been removed entirely:
CONFIG_DM9000_BASE (was only used in a single printf)
--- drivers/net/dm9000x.c | 378 ++++++++++++++++++++++++++++---------------------- include/netdev.h | 1 + 2 files changed, 215 insertions(+), 164 deletions(-)
drivers/net/dm9000x.c +214 -164
@@ -55,6 +55,7 @@ TODO: external MII is not functional, only internal at the moment.#include <net.h> #include <asm/io.h> #include <dm9000.h> +#include <malloc.h> #include "dm9000x.h"
@@ -80,7 +81,9 @@ TODO: external MII is not functional, only internal at the moment.#endif /* Structure/enum declaration ------------------------------- */ -typedef struct board_info { +struct dm9000_priv { +ulong data_base; +ulong io_base;u32 runt_length_counter;/* counter: RX length < 64byte */ u32 long_length_counter;/* counter: RX length > 1514byte */ u32 reset_counter;/* counter: RESET */
@@ -89,23 +92,22 @@ typedef struct board_info {u16 tx_pkt_cnt;u16 queue_start_addr;u16 dbug_cnt; +u8 has_srom;u8 phy_addr;u8 device_wait_reset;/* device state */ unsigned char srom[128 ]; -void (*outblk)(volatile void *data_ptr,int count); -void (*inblk)(void *data_ptr,int count); -void (*rx_status)(u16 *RxStatus,u16 *RxLen); -struct eth_device netdev; -} board_info_t; -static board_info_t dm9000_info; +void (*outblk)(struct eth_device *dev,volatile void *data_ptr,int count); +void (*inblk)(struct eth_device *dev,void *data_ptr,int count); +void (*rx_status)(struct eth_device *dev,u16 *RxStatus,u16 *RxLen); +};/* function declaration ------------------------------------- */ -static int dm9000_probe (void ); -static u16 dm9000_phy_read (int ); -static void dm9000_phy_write (int ,u16 ); -static u8 DM9000_ior (int ); -static void DM9000_iow (int reg,u8 value); +static int dm9000_probe (struct eth_device *); +static u16 dm9000_phy_read (struct eth_device *,int ); +static void dm9000_phy_write (struct eth_device *,int ,u16 ); +static u8 DM9000_ior (struct eth_device *,int ); +static void DM9000_iow (struct eth_device *,int reg,u8 value);/* DM9000 network board routine ---------------------------- */ #ifndef CONFIG_DM9000_BYTE_SWAPPED
@@ -126,125 +128,138 @@ static void DM9000_iow(int reg, u8 value);#ifdef CONFIG_DM9000_DEBUG static void -dump_regs (void ) __attribute__ ((unused)) +dump_regs (struct eth_device *dev) __attribute__ ((unused)) {DM9000_DBG ("\n" ); -DM9000_DBG ("NCR (0x00): %02x\n" ,DM9000_ior (0 )); -DM9000_DBG ("NSR (0x01): %02x\n" ,DM9000_ior (1 )); -DM9000_DBG ("TCR (0x02): %02x\n" ,DM9000_ior (2 )); -DM9000_DBG ("TSRI (0x03): %02x\n" ,DM9000_ior (3 )); -DM9000_DBG ("TSRII (0x04): %02x\n" ,DM9000_ior (4 )); -DM9000_DBG ("RCR (0x05): %02x\n" ,DM9000_ior (5 )); -DM9000_DBG ("RSR (0x06): %02x\n" ,DM9000_ior (6 )); -DM9000_DBG ("ISR (0xFE): %02x\n" ,DM9000_ior (DM9000_ISR )); +DM9000_DBG ("NCR (0x00): %02x\n" ,DM9000_ior (dev,0 )); +DM9000_DBG ("NSR (0x01): %02x\n" ,DM9000_ior (dev,1 )); +DM9000_DBG ("TCR (0x02): %02x\n" ,DM9000_ior (dev,2 )); +DM9000_DBG ("TSRI (0x03): %02x\n" ,DM9000_ior (dev,3 )); +DM9000_DBG ("TSRII (0x04): %02x\n" ,DM9000_ior (dev,4 )); +DM9000_DBG ("RCR (0x05): %02x\n" ,DM9000_ior (dev,5 )); +DM9000_DBG ("RSR (0x06): %02x\n" ,DM9000_ior (dev,6 )); +DM9000_DBG ("ISR (0xFE): %02x\n" ,DM9000_ior (dev,DM9000_ISR ));DM9000_DBG ("\n" ); }#endif -static void dm9000_outblk_8bit (volatile void *data_ptr,int count) +static void dm9000_outblk_8bit (struct eth_device *dev,volatile void *data_ptr,int count) {int i; +struct dm9000_priv *priv = dev->priv;for (i =0 ; i < count; i++) -DM9000_outb ((((u8 *) data_ptr)[i] &0xff ),DM9000_DATA ); +DM9000_outb ((((u8 *) data_ptr)[i] &0xff ), priv->data_base); } -static void dm9000_outblk_16bit (volatile void *data_ptr,int count) +static void dm9000_outblk_16bit (struct eth_device *dev,volatile void *data_ptr,int count) {int i;u32 tmplen = (count +1 ) /2 ; +struct dm9000_priv *priv = dev->priv;for (i =0 ; i < tmplen; i++) -DM9000_outw (((u16 *) data_ptr)[i],DM9000_DATA ); +DM9000_outw (((u16 *) data_ptr)[i], priv->data_base); } -static void dm9000_outblk_32bit (volatile void *data_ptr,int count) +static void dm9000_outblk_32bit (struct eth_device *dev,volatile void *data_ptr,int count) {int i;u32 tmplen = (count +3 ) /4 ; +struct dm9000_priv *priv = dev->priv;for (i =0 ; i < tmplen; i++) -DM9000_outl (((u32 *) data_ptr)[i],DM9000_DATA ); +DM9000_outl (((u32 *) data_ptr)[i], priv->data_base); } -static void dm9000_inblk_8bit (void *data_ptr,int count) +static void dm9000_inblk_8bit (struct eth_device *dev,void *data_ptr,int count) {int i; +struct dm9000_priv *priv = dev->priv; +for (i =0 ; i < count; i++) - ((u8 *) data_ptr)[i] =DM9000_inb (DM9000_DATA ); + ((u8 *) data_ptr)[i] =DM9000_inb (priv->data_base); } -static void dm9000_inblk_16bit (void *data_ptr,int count) +static void dm9000_inblk_16bit (struct eth_device *dev,void *data_ptr,int count) {int i;u32 tmplen = (count +1 ) /2 ; +struct dm9000_priv *priv = dev->priv;for (i =0 ; i < tmplen; i++) - ((u16 *) data_ptr)[i] =DM9000_inw (DM9000_DATA ); + ((u16 *) data_ptr)[i] =DM9000_inw (priv->data_base); } -static void dm9000_inblk_32bit (void *data_ptr,int count) +static void dm9000_inblk_32bit (struct eth_device *dev,void *data_ptr,int count) {int i;u32 tmplen = (count +3 ) /4 ; +struct dm9000_priv *priv = dev->priv;for (i =0 ; i < tmplen; i++) - ((u32 *) data_ptr)[i] =DM9000_inl (DM9000_DATA ); + ((u32 *) data_ptr)[i] =DM9000_inl (priv->data_base); } -static void dm9000_rx_status_32bit (u16 *RxStatus,u16 *RxLen) +static void dm9000_rx_status_32bit (struct eth_device *dev,u16 *RxStatus,u16 *RxLen) {u32 tmpdata; +struct dm9000_priv *priv = dev->priv; -DM9000_outb (DM9000_MRCMD ,DM9000_IO ); +DM9000_outb (DM9000_MRCMD , priv->io_base); - tmpdata =DM9000_inl (DM9000_DATA ); + tmpdata =DM9000_inl (priv->data_base); *RxStatus =__le16_to_cpu (tmpdata); *RxLen =__le16_to_cpu (tmpdata >>16 ); } -static void dm9000_rx_status_16bit (u16 *RxStatus,u16 *RxLen) +static void dm9000_rx_status_16bit (struct eth_device *dev,u16 *RxStatus,u16 *RxLen) { -DM9000_outb (DM9000_MRCMD ,DM9000_IO ); +struct dm9000_priv *priv = dev->priv; + +DM9000_outb (DM9000_MRCMD , priv->io_base); - *RxStatus =__le16_to_cpu (DM9000_inw (DM9000_DATA )); - *RxLen =__le16_to_cpu (DM9000_inw (DM9000_DATA )); + *RxStatus =__le16_to_cpu (DM9000_inw (priv->data_base)); + *RxLen =__le16_to_cpu (DM9000_inw (priv->data_base)); } -static void dm9000_rx_status_8bit (u16 *RxStatus,u16 *RxLen) +static void dm9000_rx_status_8bit (struct eth_device *dev,u16 *RxStatus,u16 *RxLen) { -DM9000_outb (DM9000_MRCMD ,DM9000_IO ); +struct dm9000_priv *priv = dev->priv; + +DM9000_outb (DM9000_MRCMD , priv->io_base); *RxStatus = -__le16_to_cpu (DM9000_inb (DM9000_DATA ) + - (DM9000_inb (DM9000_DATA ) <<8 )); +__le16_to_cpu (DM9000_inb (priv->data_base) + + (DM9000_inb (priv->data_base) <<8 )); *RxLen = -__le16_to_cpu (DM9000_inb (DM9000_DATA ) + - (DM9000_inb (DM9000_DATA ) <<8 )); +__le16_to_cpu (DM9000_inb (priv->data_base) + + (DM9000_inb (priv->data_base) <<8 )); }/* Search DM9000 board, allocate space and register it */ int -dm9000_probe (void ) +dm9000_probe (struct eth_device *dev) { +struct dm9000_priv *priv = dev->priv;u32 id_val; - id_val =DM9000_ior (DM9000_VIDL ); - id_val |=DM9000_ior (DM9000_VIDH ) <<8 ; - id_val |=DM9000_ior (DM9000_PIDL ) <<16 ; - id_val |=DM9000_ior (DM9000_PIDH ) <<24 ; + id_val =DM9000_ior (dev,DM9000_VIDL ); + id_val |=DM9000_ior (dev,DM9000_VIDH ) <<8 ; + id_val |=DM9000_ior (dev,DM9000_PIDL ) <<16 ; + id_val |=DM9000_ior (dev,DM9000_PIDH ) <<24 ;if (id_val ==DM9000_ID ) { -printf ("dm9000 i/o: 0x%x, id: 0x%x \n" ,CONFIG_DM9000_BASE , +printf ("dm9000 i/o: 0x%lx, id: 0x%x \n" , priv->io_base, id_val);return 0 ; }else { -printf ("dm9000 not found at 0x%08x id: 0x%08x\n" , -CONFIG_DM9000_BASE , id_val); +printf ("dm9000 not found at 0x%08lx id: 0x%08x\n" , + priv->io_base, id_val);return -1 ; } }/* General Purpose dm9000 reset routine */ static void -dm9000_reset (void ) +dm9000_reset (struct eth_device *dev) {DM9000_DBG ("resetting DM9000\n" );
@@ -252,28 +267,28 @@ dm9000_reset(void)see DM9000 Application Notes V1.22 Jun 11, 2004 page 29 */ /* DEBUG: Make all GPIO0 outputs, all others inputs */ -DM9000_iow (DM9000_GPCR ,GPCR_GPIO0_OUT ); +DM9000_iow (dev,DM9000_GPCR ,GPCR_GPIO0_OUT );/* Step 1: Power internal PHY by writing 0 to GPIO0 pin */ -DM9000_iow (DM9000_GPR ,0 ); +DM9000_iow (dev,DM9000_GPR ,0 );/* Step 2: Software reset */ -DM9000_iow (DM9000_NCR , (NCR_LBK_INT_MAC |NCR_RST )); +DM9000_iow (dev,DM9000_NCR , (NCR_LBK_INT_MAC |NCR_RST ));do {DM9000_DBG ("resetting the DM9000, 1st reset\n" );udelay (25 );/* Wait at least 20 us */ - }while (DM9000_ior (DM9000_NCR ) &1 ); + }while (DM9000_ior (dev,DM9000_NCR ) &1 ); -DM9000_iow (DM9000_NCR ,0 ); -DM9000_iow (DM9000_NCR , (NCR_LBK_INT_MAC |NCR_RST ));/* Issue a second reset */ +DM9000_iow (dev,DM9000_NCR ,0 ); +DM9000_iow (dev,DM9000_NCR , (NCR_LBK_INT_MAC |NCR_RST ));/* Issue a second reset */ do {DM9000_DBG ("resetting the DM9000, 2nd reset\n" );udelay (25 );/* Wait at least 20 us */ - }while (DM9000_ior (DM9000_NCR ) &1 ); + }while (DM9000_ior (dev,DM9000_NCR ) &1 );/* Check whether the ethernet controller is present */ -if ((DM9000_ior (DM9000_PIDL ) !=0x0 ) || - (DM9000_ior (DM9000_PIDH ) !=0x90 )) +if ((DM9000_ior (dev,DM9000_PIDL ) !=0x0 ) || + (DM9000_ior (dev,DM9000_PIDH ) !=0x90 ))printf ("ERROR: resetting DM9000 -> not responding\n" ); }
@@ -283,63 +298,63 @@ static int dm9000_init(struct eth_device *dev, bd_t *bd) {int i, oft, lnk;u8 io_mode; -struct board_info *db = &dm9000_info; +struct dm9000_priv *priv = dev->priv;DM9000_DBG ("%s\n" , __func__);/* RESET device */ -dm9000_reset (); +dm9000_reset (dev); -if (dm9000_probe () <0 ) +if (dm9000_probe (dev) <0 )return -1 ;/* Auto-detect 8/16/32 bit mode, ISR Bit 6+7 indicate bus width */ - io_mode =DM9000_ior (DM9000_ISR ) >>6 ; + io_mode =DM9000_ior (dev,DM9000_ISR ) >>6 ;switch (io_mode) {case 0x0 :/* 16-bit mode */ printf ("DM9000: running in 16 bit mode\n" ); - db->outblk = dm9000_outblk_16bit; - db->inblk = dm9000_inblk_16bit; - db->rx_status = dm9000_rx_status_16bit; + priv->outblk = dm9000_outblk_16bit; + priv->inblk = dm9000_inblk_16bit; + priv->rx_status = dm9000_rx_status_16bit;break ;case 0x01 :/* 32-bit mode */ printf ("DM9000: running in 32 bit mode\n" ); - db->outblk = dm9000_outblk_32bit; - db->inblk = dm9000_inblk_32bit; - db->rx_status = dm9000_rx_status_32bit; + priv->outblk = dm9000_outblk_32bit; + priv->inblk = dm9000_inblk_32bit; + priv->rx_status = dm9000_rx_status_32bit;break ;case 0x02 :/* 8 bit mode */ printf ("DM9000: running in 8 bit mode\n" ); - db->outblk = dm9000_outblk_8bit; - db->inblk = dm9000_inblk_8bit; - db->rx_status = dm9000_rx_status_8bit; + priv->outblk = dm9000_outblk_8bit; + priv->inblk = dm9000_inblk_8bit; + priv->rx_status = dm9000_rx_status_8bit;break ;default :/* Assume 8 bit mode, will probably not work anyway */ printf ("DM9000: Undefined IO-mode:0x%x\n" , io_mode); - db->outblk = dm9000_outblk_8bit; - db->inblk = dm9000_inblk_8bit; - db->rx_status = dm9000_rx_status_8bit; + priv->outblk = dm9000_outblk_8bit; + priv->inblk = dm9000_inblk_8bit; + priv->rx_status = dm9000_rx_status_8bit;break ; }/* Program operating register, only internal phy supported */ -DM9000_iow (DM9000_NCR ,0x0 ); +DM9000_iow (dev,DM9000_NCR ,0x0 );/* TX Polling clear */ -DM9000_iow (DM9000_TCR ,0 ); +DM9000_iow (dev,DM9000_TCR ,0 );/* Less 3Kb, 200us */ -DM9000_iow (DM9000_BPTR ,BPTR_BPHW (3 ) |BPTR_JPT_600US ); +DM9000_iow (dev,DM9000_BPTR ,BPTR_BPHW (3 ) |BPTR_JPT_600US );/* Flow Control : High/Low Water */ -DM9000_iow (DM9000_FCTR ,FCTR_HWOT (3 ) |FCTR_LWOT (8 )); +DM9000_iow (dev,DM9000_FCTR ,FCTR_HWOT (3 ) |FCTR_LWOT (8 ));/* SH FIXME: This looks strange! Flow Control */ -DM9000_iow (DM9000_FCR ,0x0 ); +DM9000_iow (dev,DM9000_FCR ,0x0 );/* Special Mode */ -DM9000_iow (DM9000_SMCR ,0 ); +DM9000_iow (dev,DM9000_SMCR ,0 );/* clear TX status */ -DM9000_iow (DM9000_NSR ,NSR_WAKEST |NSR_TX2END |NSR_TX1END ); +DM9000_iow (dev,DM9000_NSR ,NSR_WAKEST |NSR_TX2END |NSR_TX1END );/* Clear interrupt status */ -DM9000_iow (DM9000_ISR ,ISR_ROOS |ISR_ROS |ISR_PTS |ISR_PRS ); +DM9000_iow (dev,DM9000_ISR ,ISR_ROOS |ISR_ROS |ISR_PTS |ISR_PRS );printf ("MAC: %pM\n" , dev->enetaddr);if (!is_valid_ether_addr (dev->enetaddr)) {
@@ -354,23 +369,23 @@ static int dm9000_init(struct eth_device *dev, bd_t *bd)/* fill device MAC address registers */ for (i =0 , oft =DM9000_PAR ; i <6 ; i++, oft++) -DM9000_iow (oft, dev->enetaddr[i]); +DM9000_iow (dev, oft, dev->enetaddr[i]);for (i =0 , oft =0x16 ; i <8 ; i++, oft++) -DM9000_iow (oft,0xff ); +DM9000_iow (dev, oft,0xff );/* read back mac, just to be sure */ for (i =0 , oft =0x10 ; i <6 ; i++, oft++) -DM9000_DBG ("%02x:" ,DM9000_ior (oft)); +DM9000_DBG ("%02x:" ,DM9000_ior (dev, oft));DM9000_DBG ("\n" );/* Activate DM9000 */ /* RX enable */ -DM9000_iow (DM9000_RCR ,RCR_DIS_LONG |RCR_DIS_CRC |RCR_RXEN ); +DM9000_iow (dev,DM9000_RCR ,RCR_DIS_LONG |RCR_DIS_CRC |RCR_RXEN );/* Enable TX/RX interrupt mask */ -DM9000_iow (DM9000_IMR ,IMR_PAR ); +DM9000_iow (dev,DM9000_IMR ,IMR_PAR ); i =0 ; -while (!(dm9000_phy_read (1 ) &0x20 )) {/* autonegation complete bit */ +while (!(dm9000_phy_read (dev,1 ) &0x20 )) {/* autonegation complete bit */ udelay (1000 ); i++;if (i ==10000 ) {
@@ -380,7 +395,7 @@ static int dm9000_init(struct eth_device *dev, bd_t *bd) }/* see what we've got */ - lnk =dm9000_phy_read (17 ) >>12 ; + lnk =dm9000_phy_read (dev,17 ) >>12 ;printf ("operating at " );switch (lnk) {case 1 :
@@ -407,38 +422,38 @@ static int dm9000_init(struct eth_device *dev, bd_t *bd)Hardware start transmission. Send a packet to media from the upper layer. */ -static int dm9000_send (struct eth_device *netdev,void *packet,int length) +static int dm9000_send (struct eth_device *dev,void *packet,int length) {int tmo; -struct board_info *db = &dm9000_info; +struct dm9000_priv *priv = dev->priv;DM9000_DMP_PACKET (__func__ , packet, length); -DM9000_iow (DM9000_ISR ,IMR_PTM );/* Clear Tx bit in ISR */ +DM9000_iow (dev,DM9000_ISR ,IMR_PTM );/* Clear Tx bit in ISR */ /* Move data to DM9000 TX RAM */ -DM9000_outb (DM9000_MWCMD ,DM9000_IO );/* Prepare for TX-data */ +DM9000_outb (DM9000_MWCMD , priv->io_base);/* Prepare for TX-data */ /* push the data to the TX-fifo */ - (db->outblk)(packet, length); + (priv->outblk)(dev, packet, length);/* Set TX length to DM9000 */ -DM9000_iow (DM9000_TXPLL , length &0xff ); -DM9000_iow (DM9000_TXPLH , (length >>8 ) &0xff ); +DM9000_iow (dev,DM9000_TXPLL , length &0xff ); +DM9000_iow (dev,DM9000_TXPLH , (length >>8 ) &0xff );/* Issue TX polling command */ -DM9000_iow (DM9000_TCR ,TCR_TXREQ );/* Cleared after TX complete */ +DM9000_iow (dev,DM9000_TCR ,TCR_TXREQ );/* Cleared after TX complete */ /* wait for end of transmission */ tmo =get_timer (0 ) +5 *CONFIG_SYS_HZ ; -while ( !(DM9000_ior (DM9000_NSR ) & (NSR_TX1END |NSR_TX2END )) || - !(DM9000_ior (DM9000_ISR ) &IMR_PTM ) ) { +while ( !(DM9000_ior (dev,DM9000_NSR ) & (NSR_TX1END |NSR_TX2END )) || + !(DM9000_ior (dev,DM9000_ISR ) &IMR_PTM ) ) {if (get_timer (0 ) >= tmo) {printf ("transmission timeout\n" );break ; } } -DM9000_iow (DM9000_ISR ,IMR_PTM );/* Clear Tx bit in ISR */ +DM9000_iow (dev,DM9000_ISR ,IMR_PTM );/* Clear Tx bit in ISR */ DM9000_DBG ("transmit done\n\n" );return 0 ;
@@ -448,45 +463,45 @@ static int dm9000_send(struct eth_device *netdev, void *packet, int length)Stop the interface. The interface is stopped when it is brought. */ -static void dm9000_halt (struct eth_device *netdev) +static void dm9000_halt (struct eth_device *dev) {DM9000_DBG ("%s\n" , __func__);/* RESET devie */ -dm9000_phy_write (0 ,0x8000 );/* PHY RESET */ -DM9000_iow (DM9000_GPR ,0x01 );/* Power-Down PHY */ -DM9000_iow (DM9000_IMR ,0x80 );/* Disable all interrupt */ -DM9000_iow (DM9000_RCR ,0x00 );/* Disable RX */ +dm9000_phy_write (dev,0 ,0x8000 );/* PHY RESET */ +DM9000_iow (dev,DM9000_GPR ,0x01 );/* Power-Down PHY */ +DM9000_iow (dev,DM9000_IMR ,0x80 );/* Disable all interrupt */ +DM9000_iow (dev,DM9000_RCR ,0x00 );/* Disable RX */ }/* Received a packet and pass to upper layer */ -static int dm9000_rx (struct eth_device *netdev) +static int dm9000_rx (struct eth_device *dev) {u8 rxbyte, *rdptr = (u8 *) NetRxPackets[0 ];u16 RxStatus, RxLen =0 ; -struct board_info *db = &dm9000_info; +struct dm9000_priv *priv = dev->priv;/* Check packet ready or not, we must check the ISR status first for DM9000A */ -if (!(DM9000_ior (DM9000_ISR ) &0x01 ))/* Rx-ISR bit must be set. */ +if (!(DM9000_ior (dev,DM9000_ISR ) &0x01 ))/* Rx-ISR bit must be set. */ return 0 ; -DM9000_iow (DM9000_ISR ,0x01 );/* clear PR status latched in bit 0 */ +DM9000_iow (dev,DM9000_ISR ,0x01 );/* clear PR status latched in bit 0 */ /* There is _at least_ 1 package in the fifo, read them all */ for (;;) { -DM9000_ior (DM9000_MRCMDX );/* Dummy read */ +DM9000_ior (dev,DM9000_MRCMDX );/* Dummy read */ /* Get most updated data, only look at bits 0:1, See application notes DM9000 */ - rxbyte =DM9000_inb (DM9000_DATA ) &0x03 ; + rxbyte =DM9000_inb (priv->data_base) &0x03 ;/* Status check: this byte must be 0 or 1 */ if (rxbyte >DM9000_PKT_RDY ) { -DM9000_iow (DM9000_RCR ,0x00 );/* Stop Device */ -DM9000_iow (DM9000_ISR ,0x80 );/* Stop INT request */ +DM9000_iow (dev,DM9000_RCR ,0x00 );/* Stop Device */ +DM9000_iow (dev,DM9000_ISR ,0x80 );/* Stop INT request */ printf ("DM9000 error: status check fail: 0x%x\n" , rxbyte);return 0 ;
@@ -498,13 +513,13 @@ static int dm9000_rx(struct eth_device *netdev)DM9000_DBG ("receiving packet\n" );/* A packet ready now & Get status/length */ - (db->rx_status)(&RxStatus, &RxLen); + (priv->rx_status)(dev, &RxStatus, &RxLen);DM9000_DBG ("rx status: 0x%04x rx len: %d\n" , RxStatus, RxLen);/* Move data from DM9000 */ /* Read received packet from RX SRAM */ - (db->inblk)(rdptr, RxLen); + (priv->inblk)(dev, rdptr, RxLen);if ((RxStatus &0xbf00 ) || (RxLen <0x40 ) || (RxLen >DM9000_PKT_MAX )) {
@@ -519,7 +534,7 @@ static int dm9000_rx(struct eth_device *netdev) }if (RxLen >DM9000_PKT_MAX ) {printf ("rx length too big\n" ); -dm9000_reset (); +dm9000_reset (dev); } }else {DM9000_DMP_PACKET (__func__ , rdptr, RxLen);
@@ -536,69 +551,72 @@ static int dm9000_rx(struct eth_device *netdev)*/ void dm9000_read_srom_word (struct eth_device *dev,int offset,u8 *to) { - (void )dev; -DM9000_iow (DM9000_EPAR , offset); -DM9000_iow (DM9000_EPCR ,0x4 ); +DM9000_iow (dev,DM9000_EPAR , offset); +DM9000_iow (dev,DM9000_EPCR ,0x4 );udelay (8000 ); -DM9000_iow (DM9000_EPCR ,0x0 ); - to[0 ] =DM9000_ior (DM9000_EPDRL ); - to[1 ] =DM9000_ior (DM9000_EPDRH ); +DM9000_iow (dev,DM9000_EPCR ,0x0 ); + to[0 ] =DM9000_ior (dev,DM9000_EPDRL ); + to[1 ] =DM9000_ior (dev,DM9000_EPDRH ); }void dm9000_write_srom_word (struct eth_device *dev,int offset,u16 val) { - (void )dev; -DM9000_iow (DM9000_EPAR , offset); -DM9000_iow (DM9000_EPDRH , ((val >>8 ) &0xff )); -DM9000_iow (DM9000_EPDRL , (val &0xff )); -DM9000_iow (DM9000_EPCR ,0x12 ); +DM9000_iow (dev,DM9000_EPAR , offset); +DM9000_iow (dev,DM9000_EPDRH , ((val >>8 ) &0xff )); +DM9000_iow (dev,DM9000_EPDRL , (val &0xff )); +DM9000_iow (dev,DM9000_EPCR ,0x12 );udelay (8000 ); -DM9000_iow (DM9000_EPCR ,0 ); +DM9000_iow (dev,DM9000_EPCR ,0 ); }static void dm9000_get_enetaddr (struct eth_device *dev) { -#if !defined(CONFIG_DM9000_NO_SROM ) -int i; -for (i =0 ; i <3 ; i++) -dm9000_read_srom_word (dev, i, dev->enetaddr + (2 * i)); -#endif +struct dm9000_priv *priv = dev->priv; +if (priv->has_srom) { +int i; +for (i =0 ; i <3 ; i++) +dm9000_read_srom_word (dev, i, dev->enetaddr + (2 * i)); + } }/* Read a byte from I/O port */ static u8 -DM9000_ior (int reg) +DM9000_ior (struct eth_device *dev,int reg) { -DM9000_outb (reg,DM9000_IO ); -return DM9000_inb (DM9000_DATA ); +struct dm9000_priv *priv = dev->priv; + +DM9000_outb (reg, priv->io_base); +return DM9000_inb (priv->data_base); }/* Write a byte to I/O port */ static void -DM9000_iow (int reg,u8 value) +DM9000_iow (struct eth_device *dev,int reg,u8 value) { -DM9000_outb (reg,DM9000_IO ); -DM9000_outb (value,DM9000_DATA ); +struct dm9000_priv *priv = dev->priv; + +DM9000_outb (reg, priv->io_base); +DM9000_outb (value, priv->data_base); }/* Read a word from phyxcer */ static u16 -dm9000_phy_read (int reg) +dm9000_phy_read (struct eth_device *dev,int reg) {u16 val;/* Fill the phyxcer register into REG_0C */ -DM9000_iow (DM9000_EPAR ,DM9000_PHY | reg); -DM9000_iow (DM9000_EPCR ,0xc );/* Issue phyxcer read command */ +DM9000_iow (dev,DM9000_EPAR ,DM9000_PHY | reg); +DM9000_iow (dev,DM9000_EPCR ,0xc );/* Issue phyxcer read command */ udelay (100 );/* Wait read complete */ -DM9000_iow (DM9000_EPCR ,0x0 );/* Clear phyxcer read command */ - val = (DM9000_ior (DM9000_EPDRH ) <<8 ) |DM9000_ior (DM9000_EPDRL ); +DM9000_iow (dev,DM9000_EPCR ,0x0 );/* Clear phyxcer read command */ + val = (DM9000_ior (dev,DM9000_EPDRH ) <<8 ) |DM9000_ior (dev,DM9000_EPDRL );/* The read data keeps on REG_0D & REG_0E */ DM9000_DBG ("dm9000_phy_read(0x%x): 0x%x\n" , reg, val);
@@ -609,35 +627,67 @@ dm9000_phy_read(int reg)Write a word to phyxcer */ static void -dm9000_phy_write (int reg,u16 value) +dm9000_phy_write (struct eth_device *dev,int reg,u16 value) { -/* Fill the phyxcer register into REG_0C */ -DM9000_iow (DM9000_EPAR ,DM9000_PHY | reg); +DM9000_iow (dev,DM9000_EPAR ,DM9000_PHY | reg);/* Fill the written data into REG_0D & REG_0E */ -DM9000_iow (DM9000_EPDRL , (value &0xff )); -DM9000_iow (DM9000_EPDRH , ((value >>8 ) &0xff )); -DM9000_iow (DM9000_EPCR ,0xa );/* Issue phyxcer write command */ +DM9000_iow (dev,DM9000_EPDRL , (value &0xff )); +DM9000_iow (dev,DM9000_EPDRH , ((value >>8 ) &0xff )); +DM9000_iow (dev,DM9000_EPCR ,0xa );/* Issue phyxcer write command */ udelay (500 );/* Wait write complete */ -DM9000_iow (DM9000_EPCR ,0x0 );/* Clear phyxcer write command */ +DM9000_iow (dev,DM9000_EPCR ,0x0 );/* Clear phyxcer write command */ DM9000_DBG ("dm9000_phy_write(reg:0x%x, value:0x%x)\n" , reg, value); } -int dm9000_initialize (bd_t *bis) +int dm9000_initialize_ex (u8 dev_num,ulong addr,ulong data,u8 has_srom) { -struct eth_device *dev = &(dm9000_info.netdev); +struct eth_device *dev; +struct dm9000_priv *priv; + + priv =malloc (sizeof (*priv)); +if (!priv) +return 1 ; + dev =malloc (sizeof (*dev)); +if (!dev) { +free (priv); +return 2 ; + } -/* Load MAC address from EEPROM */ -dm9000_get_enetaddr (dev); +memset (dev,0 ,sizeof (*dev)); +memset (priv,0 ,sizeof (*priv)); + priv->io_base = addr; + priv->data_base = data; + priv->has_srom = has_srom; + dev->priv = priv; dev->init = dm9000_init; dev->halt = dm9000_halt; dev->send = dm9000_send; dev->recv = dm9000_rx; -sprintf (dev->name,"dm9000" ); +if (dev_num >0 ) { +sprintf (dev->name,"dm9000-%hu" , dev_num); + }else { +sprintf (dev->name,"dm9000" ); + } -eth_register (dev); +/* Load MAC address from EEPROM */ +dm9000_get_enetaddr (dev); -return 0 ; +return eth_register (dev); +} + +int dm9000_initialize (bd_t *bis) +{ +#if defined(DM9000_IO ) && defined(DM9000_DATA ) +#ifdef CONFIG_DM9000_NO_SROM +u8 has_srom =0 ; +#else +u8 has_srom =1 ; +#endif +return dm9000_initialize_ex (0 ,DM9000_IO ,DM9000_DATA , has_srom); +#else +return 1 ; +#endif }
include/netdev.h +1 -0
@@ -39,6 +39,7 @@ int davinci_emac_initialize(void);int dc21x4x_initialize (bd_t *bis);int designware_initialize (ulong base_addr,u32 interface);int dm9000_initialize (bd_t *bis); +int dm9000_initialize_ex (u8 dev_num,ulong addr,ulong data,u8 has_srom);int dnet_eth_initialize (int id,void *regs,unsigned int phy_addr);int e1000_initialize (bd_t *bis);int eepro100_initialize (bd_t *bis);
Signature · 1 line
2.1.1
PATCH 3/3 dm9000: rework dm9000 to support multiple devices
This one triggered a whole bunch of check-patch issues that I need to clean-up mostly due to dm9000x.c not originally meeting all of the coding conventions. I'll send a V2 of this momentarily.
- Andy
PATCH v2 3/3 dm9000: rework dm9000 to support multiple devices
In reply to Andrew RuderThe DM9000 was hard-coded to only support one DM9000 device. This patch adds a new initialization function - dm9000_initialize_ex() - to support registering multiple (and possibly dynamic) numbers of dm9000 devices. This patch consists of:
* Change the board_info struct to a private struct under eth_device.
* Add io address/data address/srom availability information to this private struct.
* Replace all uses of DM9000_IO/DM9000_DATA with new members, ensure that the eth_device struct propagates down to all helper functions.
* Make dm9000_initialize() call dm9000_initialize_ex() with filled in information from the old preprocessor symbols (DM9000_IO, DM9000_DATA, etc.)
Overall the following parameters have been moved over to being a per-chip setting:
DM9000_IO, DM9000_DATA, CONFIG_DM9000_NO_SROM
while the following is still a global setting affecting all chips:
CONFIG_DM9000_BYTE_SWAPPED
And the following has been removed entirely:
CONFIG_DM9000_BASE (was only used in a single printf)
---
Maybe a useful exercise anyway, this patch is significantly more messy with all the whitespace cleanups. See the v1 for the changes without the noise. :)
drivers/net/dm9000x.c | 468 +++++++++++++++++++++++++++++--------------------- include/netdev.h | 1 + 2 files changed, 269 insertions(+), 200 deletions(-)
drivers/net/dm9000x.c +268 -200
@@ -29,7 +29,7 @@ v1.2 03/18/2003 Weilun Huang <[email protected]>: -------------------------------------- 12/15/2003 Initial port to u-boot by - Sascha Hauer <[email protected]> + Sascha Hauer <[email protected]> 06/03/2008 Remy Bohmer <[email protected]> - Fixed the driver to work with DM9000A.
@@ -55,6 +55,7 @@ TODO: external MII is not functional, only internal at the moment.#include <net.h> #include <asm/io.h> #include <dm9000.h> +#include <malloc.h> #include "dm9000x.h"
@@ -63,24 +64,26 @@ TODO: external MII is not functional, only internal at the moment./* #define CONFIG_DM9000_DEBUG */ #ifdef CONFIG_DM9000_DEBUG -#define DM9000_DBG(fmt,args...) printf(fmt, ##args) -#define DM9000_DMP_PACKET (func,packet,length) \ +#define DM9000_DBG(fmt, args...) printf(fmt, ##args) +#define DM9000_DMP_PACKET (func, packet, length) \ do { \ - int i; \ + int i; \ printf("%s: length: %d\n", func, length); \ for (i = 0; i < length; i++) { \ if (i % 8 == 0) \ printf("\n%s: %02x: ", func, i); \ - printf("%02x ", ((unsigned char *) packet)[i]); \ + printf("%02x ", ((unsigned char *)packet)[i]); \ } printf("\n"); \ - } while(0) + } while (0)#else -#define DM9000_DBG(fmt,args...) -#define DM9000_DMP_PACKET (func,packet,length) +#define DM9000_DBG(fmt, args...) do {} while (0) +#define DM9000_DMP_PACKET (func, packet, length) do {} while (0)#endif /* Structure/enum declaration ------------------------------- */ -typedef struct board_info { +struct dm9000_priv { +ulong data_base; +ulong io_base;u32 runt_length_counter;/* counter: RX length < 64byte */ u32 long_length_counter;/* counter: RX length > 1514byte */ u32 reset_counter;/* counter: RESET */
@@ -89,32 +92,31 @@ typedef struct board_info {u16 tx_pkt_cnt;u16 queue_start_addr;u16 dbug_cnt; +u8 has_srom;u8 phy_addr;u8 device_wait_reset;/* device state */ unsigned char srom[128 ]; -void (*outblk)(volatile void *data_ptr,int count); -void (*inblk)(void *data_ptr,int count); -void (*rx_status)(u16 *RxStatus,u16 *RxLen); -struct eth_device netdev; -} board_info_t; -static board_info_t dm9000_info; +void (*outblk)(struct eth_device *dev,void *data_ptr,int count); +void (*inblk)(struct eth_device *dev,void *data_ptr,int count); +void (*rx_status)(struct eth_device *dev,u16 *rxstatus,u16 *rxlen); +};/* function declaration ------------------------------------- */ -static int dm9000_probe (void ); -static u16 dm9000_phy_read (int ); -static void dm9000_phy_write (int ,u16 ); -static u8 DM9000_ior (int ); -static void DM9000_iow (int reg,u8 value); +static int dm9000_probe (struct eth_device *); +static u16 dm9000_phy_read (struct eth_device *,int ); +static void dm9000_phy_write (struct eth_device *,int ,u16 ); +static u8 DM9000_ior (struct eth_device *,int ); +static void DM9000_iow (struct eth_device *,int reg,u8 value);/* DM9000 network board routine ---------------------------- */ #ifndef CONFIG_DM9000_BYTE_SWAPPED -#define DM9000_outb (d,r) writeb(d, (volatile u8 *)(r)) -#define DM9000_outw (d,r) writew(d, (volatile u16 *)(r)) -#define DM9000_outl (d,r) writel(d, (volatile u32 *)(r)) -#define DM9000_inb (r) readb((volatile u8 *)(r)) -#define DM9000_inw (r) readw((volatile u16 *)(r)) -#define DM9000_inl (r) readl((volatile u32 *)(r)) +#define DM9000_outb (d, r) writeb(d, (u8 *)(r)) +#define DM9000_outw (d, r) writew(d, (u16 *)(r)) +#define DM9000_outl (d, r) writel(d, (u32 *)(r)) +#define DM9000_inb (r) readb((u8 *)(r)) +#define DM9000_inw (r) readw((u16 *)(r)) +#define DM9000_inl (r) readl((u32 *)(r))#else #define DM9000_outb (d, r) __raw_writeb(d, r)#define DM9000_outw (d, r) __raw_writew(d, r)
@@ -125,126 +127,149 @@ static void DM9000_iow(int reg, u8 value);#endif #ifdef CONFIG_DM9000_DEBUG +static void dump_regs (struct eth_device *dev) __attribute__ ((unused));static void -dump_regs (void ) __attribute__ ((unused)) +dump_regs (struct eth_device *dev) {DM9000_DBG ("\n" ); -DM9000_DBG ("NCR (0x00): %02x\n" ,DM9000_ior (0 )); -DM9000_DBG ("NSR (0x01): %02x\n" ,DM9000_ior (1 )); -DM9000_DBG ("TCR (0x02): %02x\n" ,DM9000_ior (2 )); -DM9000_DBG ("TSRI (0x03): %02x\n" ,DM9000_ior (3 )); -DM9000_DBG ("TSRII (0x04): %02x\n" ,DM9000_ior (4 )); -DM9000_DBG ("RCR (0x05): %02x\n" ,DM9000_ior (5 )); -DM9000_DBG ("RSR (0x06): %02x\n" ,DM9000_ior (6 )); -DM9000_DBG ("ISR (0xFE): %02x\n" ,DM9000_ior (DM9000_ISR )); +DM9000_DBG ("NCR (0x00): %02x\n" ,DM9000_ior (dev,0 )); +DM9000_DBG ("NSR (0x01): %02x\n" ,DM9000_ior (dev,1 )); +DM9000_DBG ("TCR (0x02): %02x\n" ,DM9000_ior (dev,2 )); +DM9000_DBG ("TSRI (0x03): %02x\n" ,DM9000_ior (dev,3 )); +DM9000_DBG ("TSRII (0x04): %02x\n" ,DM9000_ior (dev,4 )); +DM9000_DBG ("RCR (0x05): %02x\n" ,DM9000_ior (dev,5 )); +DM9000_DBG ("RSR (0x06): %02x\n" ,DM9000_ior (dev,6 )); +DM9000_DBG ("ISR (0xFE): %02x\n" ,DM9000_ior (dev,DM9000_ISR ));DM9000_DBG ("\n" ); }#endif -static void dm9000_outblk_8bit (volatile void *data_ptr,int count) +static void +dm9000_outblk_8bit (struct eth_device *dev,void *data_ptr,int count) {int i; +struct dm9000_priv *priv = dev->priv;for (i =0 ; i < count; i++) -DM9000_outb ((((u8 *) data_ptr)[i] &0xff ),DM9000_DATA ); +DM9000_outb ((((u8 *)data_ptr)[i] &0xff ), priv->data_base); } -static void dm9000_outblk_16bit (volatile void *data_ptr,int count) +static void +dm9000_outblk_16bit (struct eth_device *dev,void *data_ptr,int count) {int i;u32 tmplen = (count +1 ) /2 ; +struct dm9000_priv *priv = dev->priv;for (i =0 ; i < tmplen; i++) -DM9000_outw (((u16 *) data_ptr)[i],DM9000_DATA ); +DM9000_outw (((u16 *)data_ptr)[i], priv->data_base); } -static void dm9000_outblk_32bit (volatile void *data_ptr,int count) +static void +dm9000_outblk_32bit (struct eth_device *dev,void *data_ptr,int count) {int i;u32 tmplen = (count +3 ) /4 ; +struct dm9000_priv *priv = dev->priv;for (i =0 ; i < tmplen; i++) -DM9000_outl (((u32 *) data_ptr)[i],DM9000_DATA ); +DM9000_outl (((u32 *)data_ptr)[i], priv->data_base); } -static void dm9000_inblk_8bit (void *data_ptr,int count) +static void +dm9000_inblk_8bit (struct eth_device *dev,void *data_ptr,int count) {int i; +struct dm9000_priv *priv = dev->priv; +for (i =0 ; i < count; i++) - ((u8 *) data_ptr)[i] =DM9000_inb (DM9000_DATA ); + ((u8 *)data_ptr)[i] =DM9000_inb (priv->data_base); } -static void dm9000_inblk_16bit (void *data_ptr,int count) +static void +dm9000_inblk_16bit (struct eth_device *dev,void *data_ptr,int count) {int i;u32 tmplen = (count +1 ) /2 ; +struct dm9000_priv *priv = dev->priv;for (i =0 ; i < tmplen; i++) - ((u16 *) data_ptr)[i] =DM9000_inw (DM9000_DATA ); + ((u16 *)data_ptr)[i] =DM9000_inw (priv->data_base); } -static void dm9000_inblk_32bit (void *data_ptr,int count) +static void +dm9000_inblk_32bit (struct eth_device *dev,void *data_ptr,int count) {int i;u32 tmplen = (count +3 ) /4 ; +struct dm9000_priv *priv = dev->priv;for (i =0 ; i < tmplen; i++) - ((u32 *) data_ptr)[i] =DM9000_inl (DM9000_DATA ); + ((u32 *)data_ptr)[i] =DM9000_inl (priv->data_base); } -static void dm9000_rx_status_32bit (u16 *RxStatus,u16 *RxLen) +static void +dm9000_rx_status_32bit (struct eth_device *dev,u16 *rxstatus,u16 *rxlen) {u32 tmpdata; +struct dm9000_priv *priv = dev->priv; -DM9000_outb (DM9000_MRCMD ,DM9000_IO ); +DM9000_outb (DM9000_MRCMD , priv->io_base); - tmpdata =DM9000_inl (DM9000_DATA ); - *RxStatus =__le16_to_cpu (tmpdata); - *RxLen =__le16_to_cpu (tmpdata >>16 ); + tmpdata =DM9000_inl (priv->data_base); + *rxstatus =__le16_to_cpu (tmpdata); + *rxlen =__le16_to_cpu (tmpdata >>16 ); } -static void dm9000_rx_status_16bit (u16 *RxStatus,u16 *RxLen) +static void +dm9000_rx_status_16bit (struct eth_device *dev,u16 *rxstatus,u16 *rxlen) { -DM9000_outb (DM9000_MRCMD ,DM9000_IO ); +struct dm9000_priv *priv = dev->priv; + +DM9000_outb (DM9000_MRCMD , priv->io_base); - *RxStatus =__le16_to_cpu (DM9000_inw (DM9000_DATA )); - *RxLen =__le16_to_cpu (DM9000_inw (DM9000_DATA )); + *rxstatus =__le16_to_cpu (DM9000_inw (priv->data_base)); + *rxlen =__le16_to_cpu (DM9000_inw (priv->data_base)); } -static void dm9000_rx_status_8bit (u16 *RxStatus,u16 *RxLen) +static void +dm9000_rx_status_8bit (struct eth_device *dev,u16 *rxstatus,u16 *rxlen) { -DM9000_outb (DM9000_MRCMD ,DM9000_IO ); - - *RxStatus = -__le16_to_cpu (DM9000_inb (DM9000_DATA ) + - (DM9000_inb (DM9000_DATA ) <<8 )); - *RxLen = -__le16_to_cpu (DM9000_inb (DM9000_DATA ) + - (DM9000_inb (DM9000_DATA ) <<8 )); +struct dm9000_priv *priv = dev->priv; + +DM9000_outb (DM9000_MRCMD , priv->io_base); + + *rxstatus = +__le16_to_cpu (DM9000_inb (priv->data_base) + + (DM9000_inb (priv->data_base) <<8 )); + *rxlen = +__le16_to_cpu (DM9000_inb (priv->data_base) + + (DM9000_inb (priv->data_base) <<8 )); }/* Search DM9000 board, allocate space and register it */ int -dm9000_probe (void ) +dm9000_probe (struct eth_device *dev) { +struct dm9000_priv *priv = dev->priv;u32 id_val; - id_val =DM9000_ior (DM9000_VIDL ); - id_val |=DM9000_ior (DM9000_VIDH ) <<8 ; - id_val |=DM9000_ior (DM9000_PIDL ) <<16 ; - id_val |=DM9000_ior (DM9000_PIDH ) <<24 ; + id_val =DM9000_ior (dev,DM9000_VIDL ); + id_val |=DM9000_ior (dev,DM9000_VIDH ) <<8 ; + id_val |=DM9000_ior (dev,DM9000_PIDL ) <<16 ; + id_val |=DM9000_ior (dev,DM9000_PIDH ) <<24 ;if (id_val ==DM9000_ID ) { -printf ("dm9000 i/o: 0x%x, id: 0x%x \n" ,CONFIG_DM9000_BASE , +printf ("dm9000 i/o: 0x%lx, id: 0x%x\n" , priv->io_base, id_val);return 0 ; }else { -printf ("dm9000 not found at 0x%08x id: 0x%08x\n" , -CONFIG_DM9000_BASE , id_val); +printf ("dm9000 not found at 0x%08lx id: 0x%08x\n" , + priv->io_base, id_val);return -1 ; } }/* General Purpose dm9000 reset routine */ static void -dm9000_reset (void ) +dm9000_reset (struct eth_device *dev) {DM9000_DBG ("resetting DM9000\n" );
@@ -252,28 +277,29 @@ dm9000_reset(void)see DM9000 Application Notes V1.22 Jun 11, 2004 page 29 */ /* DEBUG: Make all GPIO0 outputs, all others inputs */ -DM9000_iow (DM9000_GPCR ,GPCR_GPIO0_OUT ); +DM9000_iow (dev,DM9000_GPCR ,GPCR_GPIO0_OUT );/* Step 1: Power internal PHY by writing 0 to GPIO0 pin */ -DM9000_iow (DM9000_GPR ,0 ); +DM9000_iow (dev,DM9000_GPR ,0 );/* Step 2: Software reset */ -DM9000_iow (DM9000_NCR , (NCR_LBK_INT_MAC |NCR_RST )); +DM9000_iow (dev,DM9000_NCR , (NCR_LBK_INT_MAC |NCR_RST ));do {DM9000_DBG ("resetting the DM9000, 1st reset\n" );udelay (25 );/* Wait at least 20 us */ - }while (DM9000_ior (DM9000_NCR ) &1 ); + }while (DM9000_ior (dev,DM9000_NCR ) &1 ); -DM9000_iow (DM9000_NCR ,0 ); -DM9000_iow (DM9000_NCR , (NCR_LBK_INT_MAC |NCR_RST ));/* Issue a second reset */ +DM9000_iow (dev,DM9000_NCR ,0 ); +/* Issue a second reset */ +DM9000_iow (dev,DM9000_NCR , (NCR_LBK_INT_MAC |NCR_RST ));do {DM9000_DBG ("resetting the DM9000, 2nd reset\n" );udelay (25 );/* Wait at least 20 us */ - }while (DM9000_ior (DM9000_NCR ) &1 ); + }while (DM9000_ior (dev,DM9000_NCR ) &1 );/* Check whether the ethernet controller is present */ -if ((DM9000_ior (DM9000_PIDL ) !=0x0 ) || - (DM9000_ior (DM9000_PIDH ) !=0x90 )) +if ((DM9000_ior (dev,DM9000_PIDL ) !=0x0 ) || + (DM9000_ior (dev,DM9000_PIDH ) !=0x90 ))printf ("ERROR: resetting DM9000 -> not responding\n" ); }
@@ -283,63 +309,63 @@ static int dm9000_init(struct eth_device *dev, bd_t *bd) {int i, oft, lnk;u8 io_mode; -struct board_info *db = &dm9000_info; +struct dm9000_priv *priv = dev->priv;DM9000_DBG ("%s\n" , __func__);/* RESET device */ -dm9000_reset (); +dm9000_reset (dev); -if (dm9000_probe () <0 ) +if (dm9000_probe (dev) <0 )return -1 ;/* Auto-detect 8/16/32 bit mode, ISR Bit 6+7 indicate bus width */ - io_mode =DM9000_ior (DM9000_ISR ) >>6 ; + io_mode =DM9000_ior (dev,DM9000_ISR ) >>6 ;switch (io_mode) {case 0x0 :/* 16-bit mode */ printf ("DM9000: running in 16 bit mode\n" ); - db->outblk = dm9000_outblk_16bit; - db->inblk = dm9000_inblk_16bit; - db->rx_status = dm9000_rx_status_16bit; + priv->outblk = dm9000_outblk_16bit; + priv->inblk = dm9000_inblk_16bit; + priv->rx_status = dm9000_rx_status_16bit;break ;case 0x01 :/* 32-bit mode */ printf ("DM9000: running in 32 bit mode\n" ); - db->outblk = dm9000_outblk_32bit; - db->inblk = dm9000_inblk_32bit; - db->rx_status = dm9000_rx_status_32bit; + priv->outblk = dm9000_outblk_32bit; + priv->inblk = dm9000_inblk_32bit; + priv->rx_status = dm9000_rx_status_32bit;break ;case 0x02 :/* 8 bit mode */ printf ("DM9000: running in 8 bit mode\n" ); - db->outblk = dm9000_outblk_8bit; - db->inblk = dm9000_inblk_8bit; - db->rx_status = dm9000_rx_status_8bit; + priv->outblk = dm9000_outblk_8bit; + priv->inblk = dm9000_inblk_8bit; + priv->rx_status = dm9000_rx_status_8bit;break ;default :/* Assume 8 bit mode, will probably not work anyway */ printf ("DM9000: Undefined IO-mode:0x%x\n" , io_mode); - db->outblk = dm9000_outblk_8bit; - db->inblk = dm9000_inblk_8bit; - db->rx_status = dm9000_rx_status_8bit; + priv->outblk = dm9000_outblk_8bit; + priv->inblk = dm9000_inblk_8bit; + priv->rx_status = dm9000_rx_status_8bit;break ; }/* Program operating register, only internal phy supported */ -DM9000_iow (DM9000_NCR ,0x0 ); +DM9000_iow (dev,DM9000_NCR ,0x0 );/* TX Polling clear */ -DM9000_iow (DM9000_TCR ,0 ); +DM9000_iow (dev,DM9000_TCR ,0 );/* Less 3Kb, 200us */ -DM9000_iow (DM9000_BPTR ,BPTR_BPHW (3 ) |BPTR_JPT_600US ); +DM9000_iow (dev,DM9000_BPTR ,BPTR_BPHW (3 ) |BPTR_JPT_600US );/* Flow Control : High/Low Water */ -DM9000_iow (DM9000_FCTR ,FCTR_HWOT (3 ) |FCTR_LWOT (8 )); +DM9000_iow (dev,DM9000_FCTR ,FCTR_HWOT (3 ) |FCTR_LWOT (8 ));/* SH FIXME: This looks strange! Flow Control */ -DM9000_iow (DM9000_FCR ,0x0 ); +DM9000_iow (dev,DM9000_FCR ,0x0 );/* Special Mode */ -DM9000_iow (DM9000_SMCR ,0 ); +DM9000_iow (dev,DM9000_SMCR ,0 );/* clear TX status */ -DM9000_iow (DM9000_NSR ,NSR_WAKEST |NSR_TX2END |NSR_TX1END ); +DM9000_iow (dev,DM9000_NSR ,NSR_WAKEST |NSR_TX2END |NSR_TX1END );/* Clear interrupt status */ -DM9000_iow (DM9000_ISR ,ISR_ROOS |ISR_ROS |ISR_PTS |ISR_PRS ); +DM9000_iow (dev,DM9000_ISR ,ISR_ROOS |ISR_ROS |ISR_PTS |ISR_PRS );printf ("MAC: %pM\n" , dev->enetaddr);if (!is_valid_ether_addr (dev->enetaddr)) {
@@ -354,23 +380,24 @@ static int dm9000_init(struct eth_device *dev, bd_t *bd)/* fill device MAC address registers */ for (i =0 , oft =DM9000_PAR ; i <6 ; i++, oft++) -DM9000_iow (oft, dev->enetaddr[i]); +DM9000_iow (dev, oft, dev->enetaddr[i]);for (i =0 , oft =0x16 ; i <8 ; i++, oft++) -DM9000_iow (oft,0xff ); +DM9000_iow (dev, oft,0xff );/* read back mac, just to be sure */ for (i =0 , oft =0x10 ; i <6 ; i++, oft++) -DM9000_DBG ("%02x:" ,DM9000_ior (oft)); +DM9000_DBG ("%02x:" ,DM9000_ior (dev, oft));DM9000_DBG ("\n" );/* Activate DM9000 */ /* RX enable */ -DM9000_iow (DM9000_RCR ,RCR_DIS_LONG |RCR_DIS_CRC |RCR_RXEN ); +DM9000_iow (dev,DM9000_RCR ,RCR_DIS_LONG |RCR_DIS_CRC |RCR_RXEN );/* Enable TX/RX interrupt mask */ -DM9000_iow (DM9000_IMR ,IMR_PAR ); +DM9000_iow (dev,DM9000_IMR ,IMR_PAR ); i =0 ; -while (!(dm9000_phy_read (1 ) &0x20 )) {/* autonegation complete bit */ +while (!(dm9000_phy_read (dev,1 ) &0x20 )) { +/* autonegotiation complete bit */ udelay (1000 ); i++;if (i ==10000 ) {
@@ -380,7 +407,7 @@ static int dm9000_init(struct eth_device *dev, bd_t *bd) }/* see what we've got */ - lnk =dm9000_phy_read (17 ) >>12 ; + lnk =dm9000_phy_read (dev,17 ) >>12 ;printf ("operating at " );switch (lnk) {case 1 :
@@ -407,38 +434,38 @@ static int dm9000_init(struct eth_device *dev, bd_t *bd)Hardware start transmission. Send a packet to media from the upper layer. */ -static int dm9000_send (struct eth_device *netdev,void *packet,int length) +static int dm9000_send (struct eth_device *dev,void *packet,int length) {int tmo; -struct board_info *db = &dm9000_info; +struct dm9000_priv *priv = dev->priv;DM9000_DMP_PACKET (__func__ , packet, length); -DM9000_iow (DM9000_ISR ,IMR_PTM );/* Clear Tx bit in ISR */ +DM9000_iow (dev,DM9000_ISR ,IMR_PTM );/* Clear Tx bit in ISR */ /* Move data to DM9000 TX RAM */ -DM9000_outb (DM9000_MWCMD ,DM9000_IO );/* Prepare for TX-data */ +DM9000_outb (DM9000_MWCMD , priv->io_base);/* Prepare for TX-data */ /* push the data to the TX-fifo */ - (db->outblk)(packet, length); + (priv->outblk)(dev, packet, length);/* Set TX length to DM9000 */ -DM9000_iow (DM9000_TXPLL , length &0xff ); -DM9000_iow (DM9000_TXPLH , (length >>8 ) &0xff ); +DM9000_iow (dev,DM9000_TXPLL , length &0xff ); +DM9000_iow (dev,DM9000_TXPLH , (length >>8 ) &0xff );/* Issue TX polling command */ -DM9000_iow (DM9000_TCR ,TCR_TXREQ );/* Cleared after TX complete */ +DM9000_iow (dev,DM9000_TCR ,TCR_TXREQ );/* Cleared after TX complete */ /* wait for end of transmission */ tmo =get_timer (0 ) +5 *CONFIG_SYS_HZ ; -while ( !(DM9000_ior (DM9000_NSR ) & (NSR_TX1END |NSR_TX2END )) || - !(DM9000_ior (DM9000_ISR ) &IMR_PTM ) ) { +while (!(DM9000_ior (dev,DM9000_NSR ) & (NSR_TX1END |NSR_TX2END )) || + !(DM9000_ior (dev,DM9000_ISR ) &IMR_PTM )) {if (get_timer (0 ) >= tmo) {printf ("transmission timeout\n" );break ; } } -DM9000_iow (DM9000_ISR ,IMR_PTM );/* Clear Tx bit in ISR */ +DM9000_iow (dev,DM9000_ISR ,IMR_PTM );/* Clear Tx bit in ISR */ DM9000_DBG ("transmit done\n\n" );return 0 ;
@@ -448,47 +475,50 @@ static int dm9000_send(struct eth_device *netdev, void *packet, int length)Stop the interface. The interface is stopped when it is brought. */ -static void dm9000_halt (struct eth_device *netdev) +static void dm9000_halt (struct eth_device *dev) {DM9000_DBG ("%s\n" , __func__);/* RESET devie */ -dm9000_phy_write (0 ,0x8000 );/* PHY RESET */ -DM9000_iow (DM9000_GPR ,0x01 );/* Power-Down PHY */ -DM9000_iow (DM9000_IMR ,0x80 );/* Disable all interrupt */ -DM9000_iow (DM9000_RCR ,0x00 );/* Disable RX */ +dm9000_phy_write (dev,0 ,0x8000 );/* PHY RESET */ +DM9000_iow (dev,DM9000_GPR ,0x01 );/* Power-Down PHY */ +DM9000_iow (dev,DM9000_IMR ,0x80 );/* Disable all interrupt */ +DM9000_iow (dev,DM9000_RCR ,0x00 );/* Disable RX */ }/* Received a packet and pass to upper layer */ -static int dm9000_rx (struct eth_device *netdev) +static int dm9000_rx (struct eth_device *dev) { -u8 rxbyte, *rdptr = (u8 *) NetRxPackets[0 ]; -u16 RxStatus, RxLen =0 ; -struct board_info *db = &dm9000_info; +u8 rxbyte, *rdptr = (u8 *)NetRxPackets[0 ]; +u16 rxstatus, rxlen =0 ; +struct dm9000_priv *priv = dev->priv;/* Check packet ready or not, we must check the ISR status first for DM9000A */ -if (!(DM9000_ior (DM9000_ISR ) &0x01 ))/* Rx-ISR bit must be set. */ +if (!(DM9000_ior (dev,DM9000_ISR ) &0x01 ))/* Rx-ISR bit must be set. */ return 0 ; -DM9000_iow (DM9000_ISR ,0x01 );/* clear PR status latched in bit 0 */ +/* clear PR status latched in bit 0 */ +DM9000_iow (dev,DM9000_ISR ,0x01 );/* There is _at least_ 1 package in the fifo, read them all */ for (;;) { -DM9000_ior (DM9000_MRCMDX );/* Dummy read */ +DM9000_ior (dev,DM9000_MRCMDX );/* Dummy read */ /* Get most updated data, only look at bits 0:1, See application notes DM9000 */ - rxbyte =DM9000_inb (DM9000_DATA ) &0x03 ; + rxbyte =DM9000_inb (priv->data_base) &0x03 ;/* Status check: this byte must be 0 or 1 */ if (rxbyte >DM9000_PKT_RDY ) { -DM9000_iow (DM9000_RCR ,0x00 );/* Stop Device */ -DM9000_iow (DM9000_ISR ,0x80 );/* Stop INT request */ +/* Stop Device */ +DM9000_iow (dev,DM9000_RCR ,0x00 ); +/* Stop INT request */ +DM9000_iow (dev,DM9000_ISR ,0x80 );printf ("DM9000 error: status check fail: 0x%x\n" , - rxbyte); + rxbyte);return 0 ; }
@@ -498,34 +528,31 @@ static int dm9000_rx(struct eth_device *netdev)DM9000_DBG ("receiving packet\n" );/* A packet ready now & Get status/length */ - (db->rx_status)(&RxStatus, &RxLen); + (priv->rx_status)(dev, &rxstatus, &rxlen); -DM9000_DBG ("rx status: 0x%04x rx len: %d\n" , RxStatus, RxLen); +DM9000_DBG ("rx status: 0x%04x rx len: %d\n" , rxstatus, rxlen);/* Move data from DM9000 */ /* Read received packet from RX SRAM */ - (db->inblk)(rdptr, RxLen); + (priv->inblk)(dev, rdptr, rxlen); -if ((RxStatus &0xbf00 ) || (RxLen <0x40 ) - || (RxLen >DM9000_PKT_MAX )) { -if (RxStatus &0x100 ) { +if ((rxstatus &0xbf00 ) || (rxlen <0x40 ) || + (rxlen >DM9000_PKT_MAX )) { +if (rxstatus &0x100 )printf ("rx fifo error\n" ); - } -if (RxStatus &0x200 ) { +if (rxstatus &0x200 )printf ("rx crc error\n" ); - } -if (RxStatus &0x8000 ) { +if (rxstatus &0x8000 )printf ("rx length error\n" ); - } -if (RxLen >DM9000_PKT_MAX ) { +if (rxlen >DM9000_PKT_MAX ) {printf ("rx length too big\n" ); -dm9000_reset (); +dm9000_reset (dev); } }else { -DM9000_DMP_PACKET (__func__ , rdptr, RxLen); +DM9000_DMP_PACKET (__func__ , rdptr, rxlen);DM9000_DBG ("passing packet to upper layer\n" ); -NetReceive (NetRxPackets[0 ], RxLen); +NetReceive (NetRxPackets[0 ], rxlen); } }return 0 ;
@@ -536,69 +563,76 @@ static int dm9000_rx(struct eth_device *netdev)*/ void dm9000_read_srom_word (struct eth_device *dev,int offset,u8 *to) { - (void )dev; -DM9000_iow (DM9000_EPAR , offset); -DM9000_iow (DM9000_EPCR ,0x4 ); +DM9000_iow (dev,DM9000_EPAR , offset); +DM9000_iow (dev,DM9000_EPCR ,0x4 );udelay (8000 ); -DM9000_iow (DM9000_EPCR ,0x0 ); - to[0 ] =DM9000_ior (DM9000_EPDRL ); - to[1 ] =DM9000_ior (DM9000_EPDRH ); +DM9000_iow (dev,DM9000_EPCR ,0x0 ); + to[0 ] =DM9000_ior (dev,DM9000_EPDRL ); + to[1 ] =DM9000_ior (dev,DM9000_EPDRH ); }void dm9000_write_srom_word (struct eth_device *dev,int offset,u16 val) { - (void )dev; -DM9000_iow (DM9000_EPAR , offset); -DM9000_iow (DM9000_EPDRH , ((val >>8 ) &0xff )); -DM9000_iow (DM9000_EPDRL , (val &0xff )); -DM9000_iow (DM9000_EPCR ,0x12 ); +DM9000_iow (dev,DM9000_EPAR , offset); +DM9000_iow (dev,DM9000_EPDRH , ((val >>8 ) &0xff )); +DM9000_iow (dev,DM9000_EPDRL , (val &0xff )); +DM9000_iow (dev,DM9000_EPCR ,0x12 );udelay (8000 ); -DM9000_iow (DM9000_EPCR ,0 ); +DM9000_iow (dev,DM9000_EPCR ,0 ); }static void dm9000_get_enetaddr (struct eth_device *dev) { -#if !defined(CONFIG_DM9000_NO_SROM ) -int i; -for (i =0 ; i <3 ; i++) -dm9000_read_srom_word (dev, i, dev->enetaddr + (2 * i)); -#endif +struct dm9000_priv *priv = dev->priv; +if (priv->has_srom) { +int i; +for (i =0 ; i <3 ; i++) +dm9000_read_srom_word (dev, i, dev->enetaddr + (2 * i)); + } }/* Read a byte from I/O port */ static u8 -DM9000_ior (int reg) +DM9000_ior (struct eth_device *dev,int reg) { -DM9000_outb (reg,DM9000_IO ); -return DM9000_inb (DM9000_DATA ); +struct dm9000_priv *priv = dev->priv; + +DM9000_outb (reg, priv->io_base); +return DM9000_inb (priv->data_base); }/* Write a byte to I/O port */ static void -DM9000_iow (int reg,u8 value) +DM9000_iow (struct eth_device *dev,int reg,u8 value) { -DM9000_outb (reg,DM9000_IO ); -DM9000_outb (value,DM9000_DATA ); +struct dm9000_priv *priv = dev->priv; + +DM9000_outb (reg, priv->io_base); +DM9000_outb (value, priv->data_base); }/* Read a word from phyxcer */ static u16 -dm9000_phy_read (int reg) +dm9000_phy_read (struct eth_device *dev,int reg) {u16 val;/* Fill the phyxcer register into REG_0C */ -DM9000_iow (DM9000_EPAR ,DM9000_PHY | reg); -DM9000_iow (DM9000_EPCR ,0xc );/* Issue phyxcer read command */ -udelay (100 );/* Wait read complete */ -DM9000_iow (DM9000_EPCR ,0x0 );/* Clear phyxcer read command */ - val = (DM9000_ior (DM9000_EPDRH ) <<8 ) |DM9000_ior (DM9000_EPDRL ); +DM9000_iow (dev,DM9000_EPAR ,DM9000_PHY | reg); +/* Issue phyxcer read command */ +DM9000_iow (dev,DM9000_EPCR ,0xc ); +/* Wait read complete */ +udelay (100 ); +/* Clear phyxcer read command */ +DM9000_iow (dev,DM9000_EPCR ,0x0 ); + val = (DM9000_ior (dev,DM9000_EPDRH ) <<8 ) | +DM9000_ior (dev,DM9000_EPDRL );/* The read data keeps on REG_0D & REG_0E */ DM9000_DBG ("dm9000_phy_read(0x%x): 0x%x\n" , reg, val);
@@ -609,35 +643,69 @@ dm9000_phy_read(int reg)Write a word to phyxcer */ static void -dm9000_phy_write (int reg,u16 value) +dm9000_phy_write (struct eth_device *dev,int reg,u16 value) { -/* Fill the phyxcer register into REG_0C */ -DM9000_iow (DM9000_EPAR ,DM9000_PHY | reg); +DM9000_iow (dev,DM9000_EPAR ,DM9000_PHY | reg);/* Fill the written data into REG_0D & REG_0E */ -DM9000_iow (DM9000_EPDRL , (value &0xff )); -DM9000_iow (DM9000_EPDRH , ((value >>8 ) &0xff )); -DM9000_iow (DM9000_EPCR ,0xa );/* Issue phyxcer write command */ -udelay (500 );/* Wait write complete */ -DM9000_iow (DM9000_EPCR ,0x0 );/* Clear phyxcer write command */ +DM9000_iow (dev,DM9000_EPDRL , (value &0xff )); +DM9000_iow (dev,DM9000_EPDRH , ((value >>8 ) &0xff )); +/* Issue phyxcer write command */ +DM9000_iow (dev,DM9000_EPCR ,0xa ); +/* Wait write complete */ +udelay (500 ); +/* Clear phyxcer write command */ +DM9000_iow (dev,DM9000_EPCR ,0x0 );DM9000_DBG ("dm9000_phy_write(reg:0x%x, value:0x%x)\n" , reg, value); } -int dm9000_initialize (bd_t *bis) +int dm9000_initialize_ex (u8 dev_num,ulong addr,ulong data,u8 has_srom) { -struct eth_device *dev = &(dm9000_info.netdev); +struct eth_device *dev; +struct dm9000_priv *priv; + + priv =malloc (sizeof (*priv)); +if (!priv) +return 1 ; + dev =malloc (sizeof (*dev)); +if (!dev) { +free (priv); +return 2 ; + } -/* Load MAC address from EEPROM */ -dm9000_get_enetaddr (dev); +memset (dev,0 ,sizeof (*dev)); +memset (priv,0 ,sizeof (*priv)); + priv->io_base = addr; + priv->data_base = data; + priv->has_srom = has_srom; + dev->priv = priv; dev->init = dm9000_init; dev->halt = dm9000_halt; dev->send = dm9000_send; dev->recv = dm9000_rx; -sprintf (dev->name,"dm9000" ); +if (dev_num >0 ) +sprintf (dev->name,"dm9000-%hu" , dev_num); +else +sprintf (dev->name,"dm9000" ); + +/* Load MAC address from EEPROM */ +dm9000_get_enetaddr (dev); -eth_register (dev); +return eth_register (dev); +} -return 0 ; +int dm9000_initialize (bd_t *bis) +{ +#if defined(DM9000_IO ) && defined(DM9000_DATA ) +#ifdef CONFIG_DM9000_NO_SROM +u8 has_srom =0 ; +#else +u8 has_srom =1 ; +#endif +return dm9000_initialize_ex (0 ,DM9000_IO ,DM9000_DATA , has_srom); +#else +return 1 ; +#endif }
include/netdev.h +1 -0
@@ -39,6 +39,7 @@ int davinci_emac_initialize(void);int dc21x4x_initialize (bd_t *bis);int designware_initialize (ulong base_addr,u32 interface);int dm9000_initialize (bd_t *bis); +int dm9000_initialize_ex (u8 dev_num,ulong addr,ulong data,u8 has_srom);int dnet_eth_initialize (int id,void *regs,unsigned int phy_addr);int e1000_initialize (bd_t *bis);int eepro100_initialize (bd_t *bis);
Signature · 1 line
2.1.1
PATCH v2 3/3 dm9000: rework dm9000 to support multiple devices
Quoted 5 lines · Andrew Ruder
The DM9000 was hard-coded to only support one DM9000 device. This patch adds a new initialization function -
dm9000_initialize_ex()- to support registering multiple (and possibly dynamic) numbers of dm9000 devices. This patch consists of:
Quoted 8 lines
* Change the
board_infostruct to a private struct undereth_device.
* Add io address/data address/srom availability information to this private struct.
* Replace all uses of DM9000_IO/DM9000_DATA with new members, ensure that theeth_devicestruct propagates down to all helper functions.
* Makedm9000_initialize()calldm9000_initialize_ex()with filled in information from the old preprocessor symbols (DM9000_IO,DM9000_DATA, etc.)
So, on new platforms we call dm9000_initialize with the right IO/DATA locations for the given device, yes? I think I'd rather update everyone else to call things the right and new way, rather than work-around supporting both.
Signature · 8 lines
Tom -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 836 bytes Desc: Digital signature URL: <http://lists.denx.de/pipermail/u-boot/attachments/20141020/c99d859f/attachment.pgp>
PATCH v2 3/3 dm9000: rework dm9000 to support multiple devices
Quoted 4 lines · Tom Rini
So, on new platforms we call
dm9000_initializewith the right IO/DATA locations for the given device, yes? I think I'd rather update everyone else to call things the right and new way, rather than work-around supporting both.
The expectation is that new platforms would move over to dm9000_initialize_ex(), dm9000_initialize() just being a shim to use what used to be #define'd in the board config.h for backwards compatibility with older boards.
There's really 3 options that I fought with:
1.) Change dm9000_initialize() to dm9000_initialize(x, y, z). PATCH #3 then also includes changes to all of the various boards.
2.) Add dm9000_initialize_ex(x, y, z), make dm9000_initialize() call dm9000_initiailize_ex(x, y, z). No boards need to change. This is what I chose.
3.) Hybrid approach, do #2, make another patch (#4) that moves everything over to dm9000_initialize_ex(x, y, z) while renaming it to dm9000_initialize(x, y, z). Seems more round-about than #1 with the same end-result, but sometimes I feel like it is a little easier to review the meat of this change (#3) without it also dealing with tons of board churn.
Thoughts?
- Andy
PATCH v2 3/3 dm9000: rework dm9000 to support multiple devices
Quoted 20 lines · Andrew Ruder
Quoted 4 lines · Tom Rini
So, on new platforms we call
dm9000_initializewith the right IO/DATA locations for the given device, yes? I think I'd rather update everyone else to call things the right and new way, rather than work-around supporting both.The expectation is that new platforms would move over to
dm9000_initialize_ex(),dm9000_initialize()just being a shim to use what used to be #define'd in the boardconfig.hfor backwards compatibility with older boards.There's really 3 options that I fought with:
1.) Change
dm9000_initialize()todm9000_initialize(x, y, z). PATCH #3 then also includes changes to all of the various boards.2.) Add
dm9000_initialize_ex(x, y, z), makedm9000_initialize()calldm9000_initiailize_ex(x, y, z). No boards need to change. This is what I chose.
Quoted 8 lines
3.) Hybrid approach, do #2, make another patch (#4) that moves everything over to
dm9000_initialize_ex(x, y, z)while renaming it todm9000_initialize(x, y, z). Seems more round-about than #1 with the same end-result, but sometimes I feel like it is a little easier to review the meat of this change (#3) without it also dealing with tons of board churn.Thoughts?
How about step 1 is checkpatch re-formatting only, step 2 is dm9000_initalize(x, y, z) but y/z aren't used, step 3 is passing around 'dev' and step 4 is the rest of the changes (so that y/z are used, if I follow all of the logic right). This splits the whitespace/etc churn out from everything else, then makes it easy enough to review that boards are converted right to the new logic.
Signature · 8 lines
Tom -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 836 bytes Desc: Digital signature URL: <http://lists.denx.de/pipermail/u-boot/attachments/20141020/2e419c5c/attachment.pgp>
PATCH v2 3/3 dm9000: rework dm9000 to support multiple devices
Hi Andrew,
Quoted 28 lines · Tom Rini
Quoted 27 lines · Andrew Ruder
Quoted 4 lines · Tom Rini
So, on new platforms we call
dm9000_initializewith the right IO/DATA locations for the given device, yes? I think I'd rather update everyone else to call things the right and new way, rather than work-around supporting both.The expectation is that new platforms would move over to
dm9000_initialize_ex(),dm9000_initialize()just being a shim to use what used to be #define'd in the boardconfig.hfor backwards compatibility with older boards.There's really 3 options that I fought with:
1.) Change
dm9000_initialize()todm9000_initialize(x, y, z). PATCH #3 then also includes changes to all of the various boards.2.) Add
dm9000_initialize_ex(x, y, z), makedm9000_initialize()calldm9000_initiailize_ex(x, y, z). No boards need to change. This is what I chose.3.) Hybrid approach, do #2, make another patch (#4) that moves everything over to
dm9000_initialize_ex(x, y, z)while renaming it todm9000_initialize(x, y, z). Seems more round-about than #1 with the same end-result, but sometimes I feel like it is a little easier to review the meat of this change (#3) without it also dealing with tons of board churn.
Quoted 8 lines
Quoted 1 line
Thoughts?
How about step 1 is checkpatch re-formatting only, step 2 is
dm9000_initalize(x, y, z)but y/z aren't used, step 3 is passing around 'dev' and step 4 is the rest of the changes (so that y/z are used, if I follow all of the logic right). This splits the whitespace/etc churn out from everything else, then makes it easy enough to review that boards are converted right to the new logic.
What ever became of this series?
Thanks,
-Joe
PATCH v2 3/3 dm9000: rework dm9000 to support multiple devices
Quoted 1 line · Joe Hershberger
What ever became of this series?
I failed to ever email it in... I have a redone series, let me clean it up and give it a quick test and make sure it works on latest... Needed to rebase on about 10 months of upstream.