Skip to content

Commit

Permalink
DM9000: Add data bus-width auto detection.
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: Ben Warren <[email protected]>
  • Loading branch information
remybohmer authored and ben-skyportsystems committed Jun 5, 2008
1 parent ea18343 commit a101361
Show file tree
Hide file tree
Showing 3 changed files with 129 additions and 66 deletions.
187 changes: 129 additions & 58 deletions drivers/net/dm9000x.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,13 @@ v1.2 03/18/2003 Weilun Huang <[email protected]>:
--------------------------------------
12/15/2003 Initial port to u-boot by Sascha Hauer <[email protected]>
12/15/2003 Initial port to u-boot by
Sascha Hauer <[email protected]>
06/03/2008 Remy Bohmer <[email protected]>
- 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.
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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();

Expand Down Expand Up @@ -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)
Expand All @@ -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);
Expand Down Expand Up @@ -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 */
Expand All @@ -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) {
Expand Down
4 changes: 0 additions & 4 deletions include/configs/scb9328.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 0 additions & 4 deletions include/configs/trizepsiv.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit a101361

Please sign in to comment.