]> git.sur5r.net Git - u-boot/commitdiff
DM9000: Add data bus-width auto detection.
authorRemy Bohmer <linux@bohmer.net>
Tue, 3 Jun 2008 13:26:21 +0000 (15:26 +0200)
committerBen Warren <biggerbadderben@gmail.com>
Thu, 5 Jun 2008 06:47:31 +0000 (23:47 -0700)
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>
drivers/net/dm9000x.c
include/configs/scb9328.h
include/configs/trizepsiv.h

index 01e2f14a9d47e177bce9e4ef2e642176844fa566..0a2ce687d87f9e90c7d64c15fd50959e4b4beb4f 100644 (file)
@@ -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) {
index d140241bff485a729edb0ecb814b1e995b41ca86..4ae25adde04c139017ad199e28fcb0ad72e87d2b 100644 (file)
 #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
index 25155ad34958bf3bdea6be7e841b1dbcf78b4797..f77dd14f1a857d27124beb65412ca2269fe54ac1 100644 (file)
 #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