summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRemy Bohmer <linux@bohmer.net>2008-06-03 15:26:21 +0200
committerBen Warren <biggerbadderben@gmail.com>2008-06-04 23:47:31 -0700
commita101361bfe23c120321e45d114c0603b8e0763e9 (patch)
tree81978bc39a9c482e63ce462b3a65b14cbedc1915
parentea183432e79fe01781abbda411968b33580a3497 (diff)
downloadu-boot-imx-a101361bfe23c120321e45d114c0603b8e0763e9.zip
u-boot-imx-a101361bfe23c120321e45d114c0603b8e0763e9.tar.gz
u-boot-imx-a101361bfe23c120321e45d114c0603b8e0763e9.tar.bz2
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 <linux@bohmer.net> Signed-off-by: Ben Warren <biggerbadderben@gmail.com>
-rw-r--r--drivers/net/dm9000x.c187
-rw-r--r--include/configs/scb9328.h4
-rw-r--r--include/configs/trizepsiv.h4
3 files changed, 129 insertions, 66 deletions
diff --git a/drivers/net/dm9000x.c b/drivers/net/dm9000x.c
index 01e2f14..0a2ce68 100644
--- a/drivers/net/dm9000x.c
+++ b/drivers/net/dm9000x.c
@@ -36,7 +36,13 @@ 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>
+ 12/15/2003 Initial port to u-boot by
+ Sascha Hauer <saschahauer@web.de>
+
+ 06/03/2008 Remy Bohmer <linux@bohmer.net>
+ - 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 d140241..4ae25ad 100644
--- a/include/configs/scb9328.h
+++ b/include/configs/scb9328.h
@@ -257,13 +257,9 @@
#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 25155ad..f77dd14 100644
--- a/include/configs/trizepsiv.h
+++ b/include/configs/trizepsiv.h
@@ -276,13 +276,9 @@
#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