From a101361bfe23c120321e45d114c0603b8e0763e9 Mon Sep 17 00:00:00 2001 From: Remy Bohmer Date: Tue, 3 Jun 2008 15:26:21 +0200 Subject: [PATCH] DM9000: Add data bus-width auto detection. The U-boot DM9000x driver contains a compile time bus-width definition for the databus connected to the network controller. This compile check makes the code unclear, inflexible and is unneccessary. It can be asked to the network controller what its bus-width is by reading bits 6 and 7 of the interrupt status register. The linux kernel already uses a runtime mechanism to determine this bus-width, so the implementation below looks somewhat like that implementation. This change has been tested with DM9000A, DM9000E, DM9000EP. Signed-off-by: Remy Bohmer Signed-off-by: Ben Warren --- drivers/net/dm9000x.c | 187 +++++++++++++++++++++++++----------- include/configs/scb9328.h | 4 - include/configs/trizepsiv.h | 4 - 3 files changed, 129 insertions(+), 66 deletions(-) diff --git a/drivers/net/dm9000x.c b/drivers/net/dm9000x.c index 01e2f14a9d..0a2ce687d8 100644 --- a/drivers/net/dm9000x.c +++ b/drivers/net/dm9000x.c @@ -36,7 +36,13 @@ v1.2 03/18/2003 Weilun Huang : -------------------------------------- - 12/15/2003 Initial port to u-boot by Sascha Hauer + 12/15/2003 Initial port to u-boot by + Sascha Hauer + + 06/03/2008 Remy Bohmer + - Added autodetect of databus width. + These changes are tested with DM9000{A,EP,E} together + with a 200MHz Atmel AT91SAM92161 core TODO: Homerun NIC and longrun NIC are not functional, only internal at the moment. @@ -84,8 +90,11 @@ typedef struct board_info { u8 device_wait_reset; /* device state */ u8 nic_type; /* NIC type */ unsigned char srom[128]; -} board_info_t; -board_info_t dmfe_info; + void (*outblk)(void *data_ptr, int count); + void (*inblk)(void *data_ptr, int count); + void (*rx_status)(u16 *RxStatus, u16 *RxLen); + } board_info_t; +static board_info_t dm9000_info; /* For module input parameter */ static int media_mode = DM9000_AUTO; @@ -127,7 +136,81 @@ dump_regs(void) DM9000_DBG("ISR (0xFE): %02x\n", DM9000_ior(ISR)); DM9000_DBG("\n"); } -#endif /* */ +#endif + +static void dm9000_outblk_8bit(void *data_ptr, int count) +{ + int i; + for (i = 0; i < count; i++) + DM9000_outb((((u8 *) data_ptr)[i] & 0xff), DM9000_DATA); +} + +static void dm9000_outblk_16bit(void *data_ptr, int count) +{ + int i; + u32 tmplen = (count + 1) / 2; + + for (i = 0; i < tmplen; i++) + DM9000_outw(((u16 *) data_ptr)[i], DM9000_DATA); +} +static void dm9000_outblk_32bit(void *data_ptr, int count) +{ + int i; + u32 tmplen = (count + 3) / 4; + + for (i = 0; i < tmplen; i++) + DM9000_outl(((u32 *) data_ptr)[i], DM9000_DATA); +} + +static void dm9000_inblk_8bit(void *data_ptr, int count) +{ + int i; + for (i = 0; i < count; i++) + ((u8 *) data_ptr)[i] = DM9000_inb(DM9000_DATA); +} + +static void dm9000_inblk_16bit(void *data_ptr, int count) +{ + int i; + u32 tmplen = (count + 1) / 2; + + for (i = 0; i < tmplen; i++) + ((u16 *) data_ptr)[i] = DM9000_inw(DM9000_DATA); +} +static void dm9000_inblk_32bit(void *data_ptr, int count) +{ + int i; + u32 tmplen = (count + 3) / 4; + + for (i = 0; i < tmplen; i++) + ((u32 *) data_ptr)[i] = DM9000_inl(DM9000_DATA); +} + +static void dm9000_rx_status_32bit(u16 *RxStatus, u16 *RxLen) +{ + u32 tmpdata = DM9000_inl(DM9000_DATA); + + DM9000_outb(DM9000_MRCMD, DM9000_IO); + + *RxStatus = tmpdata; + *RxLen = tmpdata >> 16; +} + +static void dm9000_rx_status_16bit(u16 *RxStatus, u16 *RxLen) +{ + DM9000_outb(DM9000_MRCMD, DM9000_IO); + + *RxStatus = DM9000_inw(DM9000_DATA); + *RxLen = DM9000_inw(DM9000_DATA); +} + +static void dm9000_rx_status_8bit(u16 *RxStatus, u16 *RxLen) +{ + DM9000_outb(DM9000_MRCMD, DM9000_IO); + + *RxStatus = DM9000_inb(DM9000_DATA) + (DM9000_inb(DM9000_DATA) << 8); + *RxLen = DM9000_inb(DM9000_DATA) + (DM9000_inb(DM9000_DATA) << 8); +} /* Search DM9000 board, allocate space and register it @@ -236,7 +319,7 @@ program_dm9802(void) static void identify_nic(void) { - struct board_info *db = &dmfe_info; /* Point a board information structure */ + struct board_info *db = &dm9000_info; u16 phy_reg3; DM9000_iow(DM9000_NCR, NCR_EXT_PHY); phy_reg3 = phy_read(3); @@ -274,12 +357,46 @@ int eth_init(bd_t * bd) { int i, oft, lnk; + u8 io_mode; + struct board_info *db = &dm9000_info; + DM9000_DBG("eth_init()\n"); /* RESET device */ dm9000_reset(); dm9000_probe(); + /* Auto-detect 8/16/32 bit mode, ISR Bit 6+7 indicate bus width */ + io_mode = DM9000_ior(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; + 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; + 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; + 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; + break; + } + /* NIC Type: FASTETHER, HOMERUN, LONGRUN */ identify_nic(); @@ -377,6 +494,8 @@ eth_send(volatile void *packet, int length) char *data_ptr; u32 tmplen, i; int tmo; + struct board_info *db = &dm9000_info; + DM9000_DBG("eth_send: length: %d\n", length); for (i = 0; i < length; i++) { if (i % 8 == 0) @@ -388,24 +507,8 @@ eth_send(volatile void *packet, int length) data_ptr = (char *) packet; DM9000_outb(DM9000_MWCMD, DM9000_IO); -#ifdef CONFIG_DM9000_USE_8BIT - /* Byte mode */ - for (i = 0; i < length; i++) - DM9000_outb((data_ptr[i] & 0xff), DM9000_DATA); - -#endif /* */ -#ifdef CONFIG_DM9000_USE_16BIT - tmplen = (length + 1) / 2; - for (i = 0; i < tmplen; i++) - DM9000_outw(((u16 *) data_ptr)[i], DM9000_DATA); - -#endif /* */ -#ifdef CONFIG_DM9000_USE_32BIT - tmplen = (length + 3) / 4; - for (i = 0; i < tmplen; i++) - DM9000_outl(((u32 *) data_ptr)[i], DM9000_DATA); - -#endif /* */ + /* push the data to the TX-fifo */ + (db->outblk)(data_ptr, length); /* Set TX length to DM9000 */ DM9000_iow(DM9000_TXPLL, length & 0xff); @@ -450,10 +553,7 @@ eth_rx(void) { u8 rxbyte, *rdptr = (u8 *) NetRxPackets[0]; u16 RxStatus, RxLen = 0; - u32 tmplen, i; -#ifdef CONFIG_DM9000_USE_32BIT - u32 tmpdata; -#endif + struct board_info *db = &dm9000_info; /* Check packet ready or not */ DM9000_ior(DM9000_MRCMDX); /* Dummy read */ @@ -472,43 +572,14 @@ eth_rx(void) /* A packet ready now & Get status/length */ DM9000_outb(DM9000_MRCMD, DM9000_IO); -#ifdef CONFIG_DM9000_USE_8BIT - RxStatus = DM9000_inb(DM9000_DATA) + (DM9000_inb(DM9000_DATA) << 8); - RxLen = DM9000_inb(DM9000_DATA) + (DM9000_inb(DM9000_DATA) << 8); + (db->rx_status)(&RxStatus, &RxLen); -#endif /* */ -#ifdef CONFIG_DM9000_USE_16BIT - RxStatus = DM9000_inw(DM9000_DATA); - RxLen = DM9000_inw(DM9000_DATA); - -#endif /* */ -#ifdef CONFIG_DM9000_USE_32BIT - tmpdata = DM9000_inl(DM9000_DATA); - RxStatus = tmpdata; - RxLen = tmpdata >> 16; - -#endif /* */ DM9000_DBG("rx status: 0x%04x rx len: %d\n", RxStatus, RxLen); /* Move data from DM9000 */ /* Read received packet from RX SRAM */ -#ifdef CONFIG_DM9000_USE_8BIT - for (i = 0; i < RxLen; i++) - rdptr[i] = DM9000_inb(DM9000_DATA); - -#endif /* */ -#ifdef CONFIG_DM9000_USE_16BIT - tmplen = (RxLen + 1) / 2; - for (i = 0; i < tmplen; i++) - ((u16 *) rdptr)[i] = DM9000_inw(DM9000_DATA); + (db->inblk)(rdptr, RxLen); -#endif /* */ -#ifdef CONFIG_DM9000_USE_32BIT - tmplen = (RxLen + 3) / 4; - for (i = 0; i < tmplen; i++) - ((u32 *) rdptr)[i] = DM9000_inl(DM9000_DATA); - -#endif /* */ if ((RxStatus & 0xbf00) || (RxLen < 0x40) || (RxLen > DM9000_PKT_MAX)) { if (RxStatus & 0x100) { diff --git a/include/configs/scb9328.h b/include/configs/scb9328.h index d140241bff..4ae25adde0 100644 --- a/include/configs/scb9328.h +++ b/include/configs/scb9328.h @@ -256,14 +256,10 @@ #define CFG_CS5U_VAL 0x00008400 #define CFG_CS5L_VAL 0x00000D03 -#define CONFIG_DRIVER_DM9000 1 #define CONFIG_DRIVER_DM9000 1 #define CONFIG_DM9000_BASE 0x16000000 #define DM9000_IO CONFIG_DM9000_BASE #define DM9000_DATA (CONFIG_DM9000_BASE+4) -/* #define CONFIG_DM9000_USE_8BIT */ -#define CONFIG_DM9000_USE_16BIT -/* #define CONFIG_DM9000_USE_32BIT */ /* f_{dpll}=2*f{ref}*(MFI+MFN/(MFD+1))/(PD+1) f_ref=16,777MHz diff --git a/include/configs/trizepsiv.h b/include/configs/trizepsiv.h index 25155ad349..f77dd14f1a 100644 --- a/include/configs/trizepsiv.h +++ b/include/configs/trizepsiv.h @@ -275,14 +275,10 @@ #define CFG_MCIO0_VAL 0x00008407 #define CFG_MCIO1_VAL 0x0000c108 -#define CONFIG_DRIVER_DM9000 1 #define CONFIG_DRIVER_DM9000 1 #define CONFIG_DM9000_BASE 0x08000000 #define DM9000_IO CONFIG_DM9000_BASE #define DM9000_DATA (CONFIG_DM9000_BASE+0x8004) -/* #define CONFIG_DM9000_USE_8BIT */ -/* #define CONFIG_DM9000_USE_16BIT */ -#define CONFIG_DM9000_USE_32BIT #define CONFIG_USB_OHCI_NEW 1 #define CFG_USB_OHCI_BOARD_INIT 1 -- 2.25.1