[U-Boot] [PATCH 0/3] 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.
Cc: Joe Hershberger joe.hershberger@gmail.com
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(-)

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.
Signed-off-by: Andrew Ruder andrew.ruder@elecsyscorp.com Cc: Joe Hershberger joe.hershberger@gmail.com --- drivers/net/dm9000x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/dm9000x.c b/drivers/net/dm9000x.c index 4de9d41..50a36f3 100644 --- a/drivers/net/dm9000x.c +++ b/drivers/net/dm9000x.c @@ -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));

On Mon, Oct 20, 2014 at 09:59:43AM -0500, Andrew Ruder wrote:
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.
Signed-off-by: Andrew Ruder andrew.ruder@elecsyscorp.com Cc: Joe Hershberger joe.hershberger@gmail.com
drivers/net/dm9000x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/dm9000x.c b/drivers/net/dm9000x.c index 4de9d41..50a36f3 100644 --- a/drivers/net/dm9000x.c +++ b/drivers/net/dm9000x.c @@ -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!

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 andrew.ruder@elecsyscorp.com Cc: Joe Hershberger joe.hershberger@gmail.com Cc: Stefano Babic sbabic@denx.de --- board/trizepsiv/eeprom.c | 5 +++-- drivers/net/dm9000x.c | 10 +++++----- include/dm9000.h | 8 ++++---- 3 files changed, 12 insertions(+), 11 deletions(-)
diff --git a/board/trizepsiv/eeprom.c b/board/trizepsiv/eeprom.c index 1318edc..d9045dd 100644 --- a/board/trizepsiv/eeprom.c +++ b/board/trizepsiv/eeprom.c @@ -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); }
diff --git a/drivers/net/dm9000x.c b/drivers/net/dm9000x.c index 50a36f3..230f368 100644 --- a/drivers/net/dm9000x.c +++ b/drivers/net/dm9000x.c @@ -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 }
diff --git a/include/dm9000.h b/include/dm9000.h index 42b04fa..825c32a 100644 --- a/include/dm9000.h +++ b/include/dm9000.h @@ -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__ */

Hi Andrew,
On 20/10/2014 16:59, Andrew Ruder wrote:
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 andrew.ruder@elecsyscorp.com Cc: Joe Hershberger joe.hershberger@gmail.com Cc: Stefano Babic sbabic@denx.de
Acked-by : Stefano Babic sbabic@denx.de
Best regards, Stefano Babic

On Mon, Oct 20, 2014 at 09:59:44AM -0500, Andrew Ruder wrote:
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]
-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.

On Mon, Oct 20, 2014 at 03:17:13PM -0400, Tom Rini wrote:
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

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:
* 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)
Signed-off-by: Andrew Ruder andrew.ruder@elecsyscorp.com Cc: Joe Hershberger joe.hershberger@gmail.com --- drivers/net/dm9000x.c | 378 ++++++++++++++++++++++++++++---------------------- include/netdev.h | 1 + 2 files changed, 215 insertions(+), 164 deletions(-)
diff --git a/drivers/net/dm9000x.c b/drivers/net/dm9000x.c index 230f368..2ed3121 100644 --- a/drivers/net/dm9000x.c +++ b/drivers/net/dm9000x.c @@ -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 } diff --git a/include/netdev.h b/include/netdev.h index a887bfb..5985516 100644 --- a/include/netdev.h +++ b/include/netdev.h @@ -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);

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

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:
* 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)
Signed-off-by: Andrew Ruder andrew.ruder@elecsyscorp.com Cc: Joe Hershberger joe.hershberger@gmail.com ---
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(-)
diff --git a/drivers/net/dm9000x.c b/drivers/net/dm9000x.c index 230f368..89528a8 100644 --- a/drivers/net/dm9000x.c +++ b/drivers/net/dm9000x.c @@ -29,7 +29,7 @@ v1.2 03/18/2003 Weilun Huang weilun_huang@davicom.com.tw: --------------------------------------
12/15/2003 Initial port to u-boot by - Sascha Hauer saschahauer@web.de + Sascha Hauer saschahauer@web.de
06/03/2008 Remy Bohmer linux@bohmer.net - 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 } diff --git a/include/netdev.h b/include/netdev.h index a887bfb..5985516 100644 --- a/include/netdev.h +++ b/include/netdev.h @@ -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);

On Mon, Oct 20, 2014 at 01:11:48PM -0500, Andrew Ruder wrote:
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:
- 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.)
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.

On 10/20/2014 03:00 PM, Tom Rini wrote:
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.
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

On Mon, Oct 20, 2014 at 08:16:59PM +0000, Andrew Ruder wrote:
On 10/20/2014 03:00 PM, Tom Rini wrote:
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.
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?
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.

Hi Andrew,
On Mon, Oct 20, 2014 at 6:47 PM, Tom Rini trini@ti.com wrote:
On Mon, Oct 20, 2014 at 08:16:59PM +0000, Andrew Ruder wrote:
On 10/20/2014 03:00 PM, Tom Rini wrote:
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.
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?
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

On 08/11/2015 12:58 PM, Joe Hershberger wrote:
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.
participants (5)
-
Andrew Ruder
-
Andrew Ruder
-
Joe Hershberger
-
Stefano Babic
-
Tom Rini