فهرست منبع

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>
Remy Bohmer 17 سال پیش
والد
کامیت
a101361bfe
3فایلهای تغییر یافته به همراه129 افزوده شده و 66 حذف شده
  1. 129 58
      drivers/net/dm9000x.c
  2. 0 4
      include/configs/scb9328.h
  3. 0 4
      include/configs/trizepsiv.h

+ 129 - 58
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
 TODO: Homerun NIC and longrun NIC are not functional, only internal at the
       moment.
       moment.
@@ -84,8 +90,11 @@ typedef struct board_info {
 	u8 device_wait_reset;	/* device state */
 	u8 device_wait_reset;	/* device state */
 	u8 nic_type;		/* NIC type */
 	u8 nic_type;		/* NIC type */
 	unsigned char srom[128];
 	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 */
 /* For module input parameter */
 static int media_mode = DM9000_AUTO;
 static int media_mode = DM9000_AUTO;
@@ -127,7 +136,81 @@ dump_regs(void)
 	DM9000_DBG("ISR   (0xFE): %02x\n", DM9000_ior(ISR));
 	DM9000_DBG("ISR   (0xFE): %02x\n", DM9000_ior(ISR));
 	DM9000_DBG("\n");
 	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
   Search DM9000 board, allocate space and register it
@@ -236,7 +319,7 @@ program_dm9802(void)
 static void
 static void
 identify_nic(void)
 identify_nic(void)
 {
 {
-	struct board_info *db = &dmfe_info;	/* Point a board information structure */
+	struct board_info *db = &dm9000_info;
 	u16 phy_reg3;
 	u16 phy_reg3;
 	DM9000_iow(DM9000_NCR, NCR_EXT_PHY);
 	DM9000_iow(DM9000_NCR, NCR_EXT_PHY);
 	phy_reg3 = phy_read(3);
 	phy_reg3 = phy_read(3);
@@ -274,12 +357,46 @@ int
 eth_init(bd_t * bd)
 eth_init(bd_t * bd)
 {
 {
 	int i, oft, lnk;
 	int i, oft, lnk;
+	u8 io_mode;
+	struct board_info *db = &dm9000_info;
+
 	DM9000_DBG("eth_init()\n");
 	DM9000_DBG("eth_init()\n");
 
 
 	/* RESET device */
 	/* RESET device */
 	dm9000_reset();
 	dm9000_reset();
 	dm9000_probe();
 	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 */
 	/* NIC Type: FASTETHER, HOMERUN, LONGRUN */
 	identify_nic();
 	identify_nic();
 
 
@@ -377,6 +494,8 @@ eth_send(volatile void *packet, int length)
 	char *data_ptr;
 	char *data_ptr;
 	u32 tmplen, i;
 	u32 tmplen, i;
 	int tmo;
 	int tmo;
+	struct board_info *db = &dm9000_info;
+
 	DM9000_DBG("eth_send: length: %d\n", length);
 	DM9000_DBG("eth_send: length: %d\n", length);
 	for (i = 0; i < length; i++) {
 	for (i = 0; i < length; i++) {
 		if (i % 8 == 0)
 		if (i % 8 == 0)
@@ -388,24 +507,8 @@ eth_send(volatile void *packet, int length)
 	data_ptr = (char *) packet;
 	data_ptr = (char *) packet;
 	DM9000_outb(DM9000_MWCMD, DM9000_IO);
 	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 */
 	/* Set TX length to DM9000 */
 	DM9000_iow(DM9000_TXPLL, length & 0xff);
 	DM9000_iow(DM9000_TXPLL, length & 0xff);
@@ -450,10 +553,7 @@ eth_rx(void)
 {
 {
 	u8 rxbyte, *rdptr = (u8 *) NetRxPackets[0];
 	u8 rxbyte, *rdptr = (u8 *) NetRxPackets[0];
 	u16 RxStatus, RxLen = 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 */
 	/* Check packet ready or not */
 	DM9000_ior(DM9000_MRCMDX);	/* Dummy read */
 	DM9000_ior(DM9000_MRCMDX);	/* Dummy read */
@@ -472,43 +572,14 @@ eth_rx(void)
 	/* A packet ready now  & Get status/length */
 	/* A packet ready now  & Get status/length */
 	DM9000_outb(DM9000_MRCMD, DM9000_IO);
 	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);
 	DM9000_DBG("rx status: 0x%04x rx len: %d\n", RxStatus, RxLen);
 
 
 	/* Move data from DM9000 */
 	/* Move data from DM9000 */
 	/* Read received packet from RX SRAM */
 	/* 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)
 	if ((RxStatus & 0xbf00) || (RxLen < 0x40)
 	    || (RxLen > DM9000_PKT_MAX)) {
 	    || (RxLen > DM9000_PKT_MAX)) {
 		if (RxStatus & 0x100) {
 		if (RxStatus & 0x100) {

+ 0 - 4
include/configs/scb9328.h

@@ -256,14 +256,10 @@
 #define CFG_CS5U_VAL 0x00008400
 #define CFG_CS5U_VAL 0x00008400
 #define CFG_CS5L_VAL 0x00000D03
 #define CFG_CS5L_VAL 0x00000D03
 
 
-#define CONFIG_DRIVER_DM9000		1
 #define CONFIG_DRIVER_DM9000		1
 #define CONFIG_DRIVER_DM9000		1
 #define CONFIG_DM9000_BASE		0x16000000
 #define CONFIG_DM9000_BASE		0x16000000
 #define DM9000_IO			CONFIG_DM9000_BASE
 #define DM9000_IO			CONFIG_DM9000_BASE
 #define DM9000_DATA			(CONFIG_DM9000_BASE+4)
 #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_{dpll}=2*f{ref}*(MFI+MFN/(MFD+1))/(PD+1)
    f_ref=16,777MHz
    f_ref=16,777MHz

+ 0 - 4
include/configs/trizepsiv.h

@@ -275,14 +275,10 @@
 #define CFG_MCIO0_VAL		0x00008407
 #define CFG_MCIO0_VAL		0x00008407
 #define CFG_MCIO1_VAL		0x0000c108
 #define CFG_MCIO1_VAL		0x0000c108
 
 
-#define CONFIG_DRIVER_DM9000		1
 #define CONFIG_DRIVER_DM9000		1
 #define CONFIG_DRIVER_DM9000		1
 #define CONFIG_DM9000_BASE	0x08000000
 #define CONFIG_DM9000_BASE	0x08000000
 #define DM9000_IO			CONFIG_DM9000_BASE
 #define DM9000_IO			CONFIG_DM9000_BASE
 #define DM9000_DATA			(CONFIG_DM9000_BASE+0x8004)
 #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 CONFIG_USB_OHCI_NEW	1
 #define CFG_USB_OHCI_BOARD_INIT	1
 #define CFG_USB_OHCI_BOARD_INIT	1