summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/Makefile2
-rw-r--r--drivers/cfb_console.c66
-rw-r--r--drivers/cfi_flash.c63
-rw-r--r--drivers/ct69000.c21
-rw-r--r--drivers/dc2114x.c4
-rw-r--r--drivers/e1000.c39
-rw-r--r--drivers/eepro100.c311
-rw-r--r--drivers/i8042.c19
-rw-r--r--drivers/lan91c96.h24
-rw-r--r--drivers/nand/diskonchip.c3
-rw-r--r--drivers/nand/nand.c13
-rw-r--r--drivers/nand/nand_base.c16
-rw-r--r--drivers/nand/nand_bbt.c7
-rw-r--r--drivers/nand/nand_ecc.c4
-rw-r--r--drivers/nand/nand_ids.c4
-rw-r--r--drivers/natsemi.c3
-rw-r--r--drivers/netconsole.c4
-rw-r--r--drivers/ns7520_eth.c859
-rw-r--r--drivers/ns8382x.c6
-rw-r--r--drivers/omap24xx_i2c.c17
-rw-r--r--drivers/pc_keyb.c2
-rw-r--r--drivers/pci.c2
-rw-r--r--drivers/pci_auto.c13
-rw-r--r--drivers/pci_indirect.c6
-rw-r--r--drivers/pcnet.c2
-rw-r--r--drivers/smiLynxEM.c16
-rw-r--r--drivers/tsec.c94
-rw-r--r--drivers/tsec.h5
28 files changed, 1425 insertions, 200 deletions
diff --git a/drivers/Makefile b/drivers/Makefile
index 26a556e..e6176ed 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -34,7 +34,7 @@ OBJS = 3c589.o 5701rls.o ali512x.o \
i8042.o i82365.o inca-ip_sw.o keyboard.o \
lan91c96.o \
natsemi.o ne2000.o netarm_eth.o netconsole.o \
- ns16550.o ns8382x.o ns87308.o omap1510_i2c.o \
+ ns16550.o ns8382x.o ns87308.o ns7520_eth.o omap1510_i2c.o \
omap24xx_i2c.o pci.o pci_auto.o pci_indirect.o \
pcnet.o plb2800_eth.o \
ps2ser.o ps2mult.o pc_keyb.o \
diff --git a/drivers/cfb_console.c b/drivers/cfb_console.c
index 1eaac47..9727aeb 100644
--- a/drivers/cfb_console.c
+++ b/drivers/cfb_console.c
@@ -131,6 +131,16 @@ CONFIG_VIDEO_HW_CURSOR: - Uses the hardware cursor capability of the
#endif
/*****************************************************************************/
+/* Defines for the SED13806 driver */
+/*****************************************************************************/
+#ifdef CONFIG_VIDEO_SM501
+
+#ifdef CONFIG_HH405
+#define VIDEO_FB_LITTLE_ENDIAN
+#endif
+#endif
+
+/*****************************************************************************/
/* Include video_fb.h after definitions of VIDEO_HW_RECTFILL etc */
/*****************************************************************************/
#include <video_fb.h>
@@ -372,6 +382,8 @@ static const int video_font_draw_table32[16][4] = {
{ 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff } };
+int gunzip(void *, int, unsigned char *, unsigned long *);
+
/******************************************************************************/
static void video_drawchars (int xx, int yy, unsigned char *s, int count)
@@ -489,7 +501,7 @@ static void video_drawchars (int xx, int yy, unsigned char *s, int count)
static inline void video_drawstring (int xx, int yy, unsigned char *s)
{
- video_drawchars (xx, yy, s, strlen (s));
+ video_drawchars (xx, yy, s, strlen ((char *)s));
}
/*****************************************************************************/
@@ -536,12 +548,12 @@ void console_cursor (int state)
sprintf (info, " %02d:%02d:%02d ", tm.tm_hour, tm.tm_min,
tm.tm_sec);
video_drawstring (VIDEO_VISIBLE_COLS - 10 * VIDEO_FONT_WIDTH,
- VIDEO_INFO_Y, info);
+ VIDEO_INFO_Y, (uchar *)info);
sprintf (info, "%02d.%02d.%04d", tm.tm_mday, tm.tm_mon,
tm.tm_year);
video_drawstring (VIDEO_VISIBLE_COLS - 10 * VIDEO_FONT_WIDTH,
- VIDEO_INFO_Y + 1 * VIDEO_FONT_HEIGHT, info);
+ VIDEO_INFO_Y + 1 * VIDEO_FONT_HEIGHT, (uchar *)info);
}
#endif
@@ -751,13 +763,49 @@ int video_display_bitmap (ulong bmp_image, int x, int y)
unsigned colors;
unsigned long compression;
bmp_color_table_entry_t cte;
+#ifdef CONFIG_VIDEO_BMP_GZIP
+ unsigned char *dst = NULL;
+ ulong len;
+#endif
WATCHDOG_RESET ();
if (!((bmp->header.signature[0] == 'B') &&
(bmp->header.signature[1] == 'M'))) {
+
+#ifdef CONFIG_VIDEO_BMP_GZIP
+ /*
+ * Could be a gzipped bmp image, try to decrompress...
+ */
+ len = CFG_VIDEO_LOGO_MAX_SIZE;
+ dst = malloc(CFG_VIDEO_LOGO_MAX_SIZE);
+ if (dst == NULL) {
+ printf("Error: malloc in gunzip failed!\n");
+ return(1);
+ }
+ if (gunzip(dst, CFG_VIDEO_LOGO_MAX_SIZE, (uchar *)bmp_image, &len) != 0) {
+ printf ("Error: no valid bmp or bmp.gz image at %lx\n", bmp_image);
+ free(dst);
+ return 1;
+ }
+ if (len == CFG_VIDEO_LOGO_MAX_SIZE) {
+ printf("Image could be truncated (increase CFG_VIDEO_LOGO_MAX_SIZE)!\n");
+ }
+
+ /*
+ * Set addr to decompressed image
+ */
+ bmp = (bmp_image_t *)dst;
+
+ if (!((bmp->header.signature[0] == 'B') &&
+ (bmp->header.signature[1] == 'M'))) {
+ printf ("Error: no valid bmp.gz image at %lx\n", bmp_image);
+ return 1;
+ }
+#else
printf ("Error: no valid bmp image at %lx\n", bmp_image);
return 1;
+#endif /* CONFIG_VIDEO_BMP_GZIP */
}
width = le32_to_cpu (bmp->header.width);
@@ -947,6 +995,13 @@ int video_display_bitmap (ulong bmp_image, int x, int y)
le16_to_cpu (bmp->header.bit_count));
break;
}
+
+#ifdef CONFIG_VIDEO_BMP_GZIP
+ if (dst) {
+ free(dst);
+ }
+#endif
+
return (0);
}
#endif /* (CONFIG_COMMANDS & CFG_CMD_BMP) || CONFIG_SPLASH_SCREEN */
@@ -1061,11 +1116,10 @@ static void *video_logo (void)
}
#endif /* CONFIG_SPLASH_SCREEN */
-
logo_plot (video_fb_address, VIDEO_COLS, 0, 0);
sprintf (info, " %s", &version_string);
- video_drawstring (VIDEO_INFO_X, VIDEO_INFO_Y, info);
+ video_drawstring (VIDEO_INFO_X, VIDEO_INFO_Y, (uchar *)info);
#ifdef CONFIG_CONSOLE_EXTRA_INFO
{
@@ -1076,7 +1130,7 @@ static void *video_logo (void)
if (*info)
video_drawstring (VIDEO_INFO_X,
VIDEO_INFO_Y + i * VIDEO_FONT_HEIGHT,
- info);
+ (uchar *)info);
}
}
#endif
diff --git a/drivers/cfi_flash.c b/drivers/cfi_flash.c
index 3d0f204..4b7a110 100644
--- a/drivers/cfi_flash.c
+++ b/drivers/cfi_flash.c
@@ -47,7 +47,6 @@
#include <common.h>
#include <asm/processor.h>
#include <asm/byteorder.h>
-#include <linux/byteorder/swab.h>
#include <environment.h>
#ifdef CFG_FLASH_CFI_DRIVER
@@ -167,9 +166,15 @@ typedef union {
#define NUM_ERASE_REGIONS 4
+/* use CFG_MAX_FLASH_BANKS_DETECT if defined */
+#ifdef CFG_MAX_FLASH_BANKS_DETECT
+static ulong bank_base[CFG_MAX_FLASH_BANKS_DETECT] = CFG_FLASH_BANKS_LIST;
+flash_info_t flash_info[CFG_MAX_FLASH_BANKS_DETECT]; /* FLASH chips info */
+#else
static ulong bank_base[CFG_MAX_FLASH_BANKS] = CFG_FLASH_BANKS_LIST;
+flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* FLASH chips info */
+#endif
-flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */
/*-----------------------------------------------------------------------
* Functions
@@ -185,11 +190,13 @@ static int flash_isequal (flash_info_t * info, flash_sect_t sect, uint offset, u
static int flash_isset (flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd);
static int flash_toggle (flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd);
static int flash_detect_cfi (flash_info_t * info);
-static ulong flash_get_size (ulong base, int banknum);
+ulong flash_get_size (ulong base, int banknum);
static int flash_write_cfiword (flash_info_t * info, ulong dest, cfiword_t cword);
static int flash_full_status_check (flash_info_t * info, flash_sect_t sector,
ulong tout, char *prompt);
+#if defined(CFG_ENV_IS_IN_FLASH) || defined(CFG_ENV_ADDR_REDUND) || (CFG_MONITOR_BASE >= CFG_FLASH_BASE)
static flash_info_t *flash_get_info(ulong base);
+#endif
#ifdef CFG_FLASH_USE_BUFFER_WRITE
static int flash_write_cfibuffer (flash_info_t * info, ulong dest, uchar * cp, int len);
#endif
@@ -220,7 +227,7 @@ static void flash_printqry (flash_info_t * info, flash_sect_t sect)
cfiptr_t cptr;
int x, y;
- for (x = 0; x < 0x40; x += 16 / info->portwidth) {
+ for (x = 0; x < 0x40; x += 16U / info->portwidth) {
cptr.cp =
flash_make_addr (info, sect,
x + FLASH_OFFSET_CFI_RESP);
@@ -333,8 +340,10 @@ unsigned long flash_init (void)
flash_info[i].flash_id = FLASH_UNKNOWN;
size += flash_info[i].size = flash_get_size (bank_base[i], i);
if (flash_info[i].flash_id == FLASH_UNKNOWN) {
+#ifndef CFG_FLASH_QUIET_TEST
printf ("## Unknown FLASH on Bank %d - Size = 0x%08lx = %ld MB\n",
i, flash_info[i].size, flash_info[i].size << 20);
+#endif /* CFG_FLASH_QUIET_TEST */
}
}
@@ -366,10 +375,11 @@ unsigned long flash_init (void)
/*-----------------------------------------------------------------------
*/
+#if defined(CFG_ENV_IS_IN_FLASH) || defined(CFG_ENV_ADDR_REDUND) || (CFG_MONITOR_BASE >= CFG_FLASH_BASE)
static flash_info_t *flash_get_info(ulong base)
{
int i;
- flash_info_t * info;
+ flash_info_t * info = 0;
for (i = 0; i < CFG_MAX_FLASH_BANKS; i ++) {
info = & flash_info[i];
@@ -380,6 +390,7 @@ static flash_info_t *flash_get_info(ulong base)
return i == CFG_MAX_FLASH_BANKS ? 0 : info;
}
+#endif
/*-----------------------------------------------------------------------
*/
@@ -498,11 +509,11 @@ void flash_print_info (flash_info_t * info)
info->start[i],
erased ? " E" : " ",
info->protect[i] ? "RO " : " ");
-#else
+#else /* ! CFG_FLASH_EMPTY_INFO */
if ((i % 5) == 0)
printf ("\n ");
printf (" %08lX%s",
- info->start[i], info->protect[i] ? " (RO) " : " ");
+ info->start[i], info->protect[i] ? " (RO)" : " ");
#endif
}
putc ('\n');
@@ -639,7 +650,7 @@ void flash_read_user_serial (flash_info_t * info, void *buffer, int offset,
src = flash_make_addr (info, 0, FLASH_OFFSET_USER_PROTECTION);
flash_write_cmd (info, 0, 0, FLASH_CMD_READ_ID);
memcpy (dst, src + offset, len);
- flash_write_cmd (info, 0, 0, FLASH_CMD_RESET);
+ flash_write_cmd (info, 0, 0, info->cmd_reset);
}
/*
@@ -653,7 +664,7 @@ void flash_read_factory_serial (flash_info_t * info, void *buffer, int offset,
src = flash_make_addr (info, 0, FLASH_OFFSET_INTEL_PROTECTION);
flash_write_cmd (info, 0, 0, FLASH_CMD_READ_ID);
memcpy (buffer, src + offset, len);
- flash_write_cmd (info, 0, 0, FLASH_CMD_RESET);
+ flash_write_cmd (info, 0, 0, info->cmd_reset);
}
#endif /* CFG_FLASH_PROTECTION */
@@ -738,7 +749,7 @@ static int flash_full_status_check (flash_info_t * info, flash_sect_t sector,
if (flash_isset (info, sector, 0, FLASH_STATUS_VPENS))
puts ("Vpp Low Error.\n");
}
- flash_write_cmd (info, sector, 0, FLASH_CMD_RESET);
+ flash_write_cmd (info, sector, 0, info->cmd_reset);
break;
default:
break;
@@ -797,32 +808,14 @@ static void flash_add_byte (flash_info_t * info, cfiword_t * cword, uchar c)
static void flash_make_cmd (flash_info_t * info, uchar cmd, void *cmdbuf)
{
int i;
-
-#if defined(__LITTLE_ENDIAN)
- ushort stmpw;
- uint stmpi;
-#endif
uchar *cp = (uchar *) cmdbuf;
- for (i = 0; i < info->portwidth; i++)
- *cp++ = ((i + 1) & (info->chipwidth - 1)) ? '\0' : cmd;
#if defined(__LITTLE_ENDIAN)
- switch (info->portwidth) {
- case FLASH_CFI_8BIT:
- break;
- case FLASH_CFI_16BIT:
- stmpw = *(ushort *) cmdbuf;
- *(ushort *) cmdbuf = __swab16 (stmpw);
- break;
- case FLASH_CFI_32BIT:
- stmpi = *(uint *) cmdbuf;
- *(uint *) cmdbuf = __swab32 (stmpi);
- break;
- default:
- puts ("WARNING: flash_make_cmd: unsuppported LittleEndian mode\n");
- break;
- }
+ for (i = info->portwidth; i > 0; i--)
+#else
+ for (i = 1; i <= info->portwidth; i++)
#endif
+ *cp++ = (i & (info->chipwidth - 1)) ? '\0' : cmd;
}
/*
@@ -997,7 +990,7 @@ static int flash_detect_cfi (flash_info_t * info)
for (info->chipwidth = FLASH_CFI_BY8;
info->chipwidth <= info->portwidth;
info->chipwidth <<= 1) {
- flash_write_cmd (info, 0, 0, FLASH_CMD_RESET);
+ flash_write_cmd (info, 0, 0, info->cmd_reset);
flash_write_cmd (info, 0, FLASH_OFFSET_CFI, FLASH_CMD_CFI);
if (flash_isequal (info, 0, FLASH_OFFSET_CFI_RESP, 'Q')
&& flash_isequal (info, 0, FLASH_OFFSET_CFI_RESP + 1, 'R')
@@ -1022,7 +1015,7 @@ static int flash_detect_cfi (flash_info_t * info)
* The following code cannot be run from FLASH!
*
*/
-static ulong flash_get_size (ulong base, int banknum)
+ulong flash_get_size (ulong base, int banknum)
{
flash_info_t *info = &flash_info[banknum];
int i, j;
@@ -1121,7 +1114,7 @@ static ulong flash_get_size (ulong base, int banknum)
}
}
- flash_write_cmd (info, 0, 0, FLASH_CMD_RESET);
+ flash_write_cmd (info, 0, 0, info->cmd_reset);
return (info->size);
}
diff --git a/drivers/ct69000.c b/drivers/ct69000.c
index 7bcf19f..29d82e4 100644
--- a/drivers/ct69000.c
+++ b/drivers/ct69000.c
@@ -272,6 +272,9 @@ struct ctfb_chips_properties {
static const struct ctfb_chips_properties chips[] = {
{PCI_DEVICE_ID_CT_69000, 0x200000, 1, 4, -2, 3, 257, 100, 220},
+#ifdef CONFIG_USE_CPCIDVI
+ {PCI_DEVICE_ID_CT_69030, 0x400000, 1, 4, -2, 3, 257, 100, 220},
+#endif
{PCI_DEVICE_ID_CT_65555, 0x100000, 16, 4, 0, 1, 255, 48, 220}, /* NOT TESTED */
{0, 0, 0, 0, 0, 0, 0, 0, 0} /* Terminator */
};
@@ -957,6 +960,9 @@ SetDrawingEngine (int bits_per_pixel)
*/
static struct pci_device_id supported[] = {
{PCI_VENDOR_ID_CT, PCI_DEVICE_ID_CT_69000},
+#ifdef CONFIG_USE_CPCIDVI
+ {PCI_VENDOR_ID_CT, PCI_DEVICE_ID_CT_69030},
+#endif
{}
};
@@ -1121,7 +1127,22 @@ video_hw_init (void)
pGD->cprBase = pci_mem_base; /* Dummy */
/* set up Hardware */
+#ifdef CONFIG_USE_CPCIDVI
+ if (device_id == PCI_DEVICE_ID_CT_69030) {
+ ctWrite (CT_MSR_W_O, 0x0b);
+ ctWrite (0x3cd, 0x13);
+ ctWrite_i (CT_FP_O, 0x02, 0x00);
+ ctWrite_i (CT_FP_O, 0x05, 0x00);
+ ctWrite_i (CT_FP_O, 0x06, 0x00);
+ ctWrite (0x3c2, 0x0b);
+ ctWrite_i (CT_FP_O, 0x02, 0x10);
+ ctWrite_i (CT_FP_O, 0x01, 0x09);
+ } else {
+ ctWrite (CT_MSR_W_O, 0x01);
+ }
+#else
ctWrite (CT_MSR_W_O, 0x01);
+#endif
/* set the extended Registers */
ctLoadRegs (CT_XR_O, xreg);
diff --git a/drivers/dc2114x.c b/drivers/dc2114x.c
index 5386d92..c43cd5e 100644
--- a/drivers/dc2114x.c
+++ b/drivers/dc2114x.c
@@ -214,7 +214,7 @@ int dc21x4x_initialize(bd_t *bis)
{
int idx=0;
int card_number = 0;
- int cfrv;
+ unsigned int cfrv;
unsigned char timer;
pci_dev_t devbusfn;
unsigned int iobase;
@@ -708,7 +708,7 @@ static int write_srom(struct eth_device *dev, u_long ioaddr, int index, int new_
#ifndef CONFIG_TULIP_FIX_DAVICOM
static void read_hw_addr(struct eth_device *dev, bd_t *bis)
{
- u_short tmp, *p = (short *)(&dev->enetaddr[0]);
+ u_short tmp, *p = (u_short *)(&dev->enetaddr[0]);
int i, j = 0;
for (i = 0; i < (ETH_ALEN >> 1); i++) {
diff --git a/drivers/e1000.c b/drivers/e1000.c
index cc50c26..927acbb 100644
--- a/drivers/e1000.c
+++ b/drivers/e1000.c
@@ -112,6 +112,7 @@ static int e1000_detect_gig_phy(struct e1000_hw *hw);
readl((a)->hw_addr + E1000_##reg + ((offset) << 2)))
#define E1000_WRITE_FLUSH(a) {uint32_t x; x = E1000_READ_REG(a, STATUS);}
+#ifndef CONFIG_AP1000 /* remove for warnings */
/******************************************************************************
* Raises the EEPROM's clock input.
*
@@ -478,6 +479,7 @@ e1000_validate_eeprom_checksum(struct eth_device *nic)
return -E1000_ERR_EEPROM;
}
}
+#endif /* #ifndef CONFIG_AP1000 */
/******************************************************************************
* Reads the adapter's MAC address from the EEPROM and inverts the LSB for the
@@ -488,6 +490,7 @@ e1000_validate_eeprom_checksum(struct eth_device *nic)
static int
e1000_read_mac_addr(struct eth_device *nic)
{
+#ifndef CONFIG_AP1000
struct e1000_hw *hw = nic->priv;
uint16_t offset;
uint16_t eeprom_data;
@@ -509,6 +512,32 @@ e1000_read_mac_addr(struct eth_device *nic)
/* Invert the last bit if this is the second device */
nic->enetaddr[5] += 1;
}
+#else
+ /*
+ * The AP1000's e1000 has no eeprom; the MAC address is stored in the
+ * environment variables. Currently this does not support the addition
+ * of a PMC e1000 card, which is certainly a possibility, so this should
+ * be updated to properly use the env variable only for the onboard e1000
+ */
+
+ int ii;
+ char *s, *e;
+
+ DEBUGFUNC();
+
+ s = getenv ("ethaddr");
+ if (s == NULL){
+ return -E1000_ERR_EEPROM;
+ }
+ else{
+ for(ii = 0; ii < 6; ii++) {
+ nic->enetaddr[ii] = s ? simple_strtoul (s, &e, 16) : 0;
+ if (s){
+ s = (*e) ? e + 1 : e;
+ }
+ }
+ }
+#endif
return 0;
}
@@ -876,6 +905,7 @@ e1000_setup_link(struct eth_device *nic)
DEBUGFUNC();
+#ifndef CONFIG_AP1000
/* Read and store word 0x0F of the EEPROM. This word contains bits
* that determine the hardware's default PAUSE (flow control) mode,
* a bit that determines whether the HW defaults to enabling or
@@ -888,6 +918,11 @@ e1000_setup_link(struct eth_device *nic)
DEBUGOUT("EEPROM Read Error\n");
return -E1000_ERR_EEPROM;
}
+#else
+ /* we have to hardcode the proper value for our hardware. */
+ /* this value is for the 82540EM pci card used for prototyping, and it works. */
+ eeprom_data = 0xb220;
+#endif
if (hw->fc == e1000_fc_default) {
if ((eeprom_data & EEPROM_WORD0F_PAUSE_MASK) == 0)
@@ -2787,7 +2822,7 @@ e1000_poll(struct eth_device *nic)
if (!(le32_to_cpu(rd->status)) & E1000_RXD_STAT_DD)
return 0;
/*DEBUGOUT("recv: packet len=%d \n", rd->length); */
- NetReceive(packet, le32_to_cpu(rd->length));
+ NetReceive((uchar *)packet, le32_to_cpu(rd->length));
fill_rx(hw);
return 1;
}
@@ -2950,12 +2985,14 @@ e1000_initialize(bd_t * bis)
free(nic);
return 0;
}
+#ifndef CONFIG_AP1000
if (e1000_validate_eeprom_checksum(nic) < 0) {
printf("The EEPROM Checksum Is Not Valid\n");
free(hw);
free(nic);
return 0;
}
+#endif
e1000_read_mac_addr(nic);
E1000_WRITE_REG(hw, PBA, E1000_DEFAULT_PBA);
diff --git a/drivers/eepro100.c b/drivers/eepro100.c
index 906159e..04c17f6 100644
--- a/drivers/eepro100.c
+++ b/drivers/eepro100.c
@@ -26,6 +26,7 @@
#include <net.h>
#include <asm/io.h>
#include <pci.h>
+#include <miiphy.h>
#undef DEBUG
@@ -34,67 +35,67 @@
/* Ethernet chip registers.
*/
-#define SCBStatus 0 /* Rx/Command Unit Status *Word* */
-#define SCBIntAckByte 1 /* Rx/Command Unit STAT/ACK byte */
-#define SCBCmd 2 /* Rx/Command Unit Command *Word* */
-#define SCBIntrCtlByte 3 /* Rx/Command Unit Intr.Control Byte */
-#define SCBPointer 4 /* General purpose pointer. */
-#define SCBPort 8 /* Misc. commands and operands. */
-#define SCBflash 12 /* Flash memory control. */
-#define SCBeeprom 14 /* EEPROM memory control. */
-#define SCBCtrlMDI 16 /* MDI interface control. */
-#define SCBEarlyRx 20 /* Early receive byte count. */
-#define SCBGenControl 28 /* 82559 General Control Register */
-#define SCBGenStatus 29 /* 82559 General Status register */
+#define SCBStatus 0 /* Rx/Command Unit Status *Word* */
+#define SCBIntAckByte 1 /* Rx/Command Unit STAT/ACK byte */
+#define SCBCmd 2 /* Rx/Command Unit Command *Word* */
+#define SCBIntrCtlByte 3 /* Rx/Command Unit Intr.Control Byte */
+#define SCBPointer 4 /* General purpose pointer. */
+#define SCBPort 8 /* Misc. commands and operands. */
+#define SCBflash 12 /* Flash memory control. */
+#define SCBeeprom 14 /* EEPROM memory control. */
+#define SCBCtrlMDI 16 /* MDI interface control. */
+#define SCBEarlyRx 20 /* Early receive byte count. */
+#define SCBGenControl 28 /* 82559 General Control Register */
+#define SCBGenStatus 29 /* 82559 General Status register */
/* 82559 SCB status word defnitions
*/
-#define SCB_STATUS_CX 0x8000 /* CU finished command (transmit) */
-#define SCB_STATUS_FR 0x4000 /* frame received */
-#define SCB_STATUS_CNA 0x2000 /* CU left active state */
-#define SCB_STATUS_RNR 0x1000 /* receiver left ready state */
-#define SCB_STATUS_MDI 0x0800 /* MDI read/write cycle done */
-#define SCB_STATUS_SWI 0x0400 /* software generated interrupt */
-#define SCB_STATUS_FCP 0x0100 /* flow control pause interrupt */
+#define SCB_STATUS_CX 0x8000 /* CU finished command (transmit) */
+#define SCB_STATUS_FR 0x4000 /* frame received */
+#define SCB_STATUS_CNA 0x2000 /* CU left active state */
+#define SCB_STATUS_RNR 0x1000 /* receiver left ready state */
+#define SCB_STATUS_MDI 0x0800 /* MDI read/write cycle done */
+#define SCB_STATUS_SWI 0x0400 /* software generated interrupt */
+#define SCB_STATUS_FCP 0x0100 /* flow control pause interrupt */
-#define SCB_INTACK_MASK 0xFD00 /* all the above */
+#define SCB_INTACK_MASK 0xFD00 /* all the above */
-#define SCB_INTACK_TX (SCB_STATUS_CX | SCB_STATUS_CNA)
-#define SCB_INTACK_RX (SCB_STATUS_FR | SCB_STATUS_RNR)
+#define SCB_INTACK_TX (SCB_STATUS_CX | SCB_STATUS_CNA)
+#define SCB_INTACK_RX (SCB_STATUS_FR | SCB_STATUS_RNR)
/* System control block commands
*/
/* CU Commands */
-#define CU_NOP 0x0000
-#define CU_START 0x0010
-#define CU_RESUME 0x0020
-#define CU_STATSADDR 0x0040 /* Load Dump Statistics ctrs addr */
-#define CU_SHOWSTATS 0x0050 /* Dump statistics counters. */
-#define CU_ADDR_LOAD 0x0060 /* Base address to add to CU commands */
-#define CU_DUMPSTATS 0x0070 /* Dump then reset stats counters. */
+#define CU_NOP 0x0000
+#define CU_START 0x0010
+#define CU_RESUME 0x0020
+#define CU_STATSADDR 0x0040 /* Load Dump Statistics ctrs addr */
+#define CU_SHOWSTATS 0x0050 /* Dump statistics counters. */
+#define CU_ADDR_LOAD 0x0060 /* Base address to add to CU commands */
+#define CU_DUMPSTATS 0x0070 /* Dump then reset stats counters. */
/* RUC Commands */
-#define RUC_NOP 0x0000
-#define RUC_START 0x0001
-#define RUC_RESUME 0x0002
-#define RUC_ABORT 0x0004
-#define RUC_ADDR_LOAD 0x0006 /* (seems not to clear on acceptance) */
-#define RUC_RESUMENR 0x0007
-
-#define CU_CMD_MASK 0x00f0
-#define RU_CMD_MASK 0x0007
-
-#define SCB_M 0x0100 /* 0 = enable interrupt, 1 = disable */
-#define SCB_SWI 0x0200 /* 1 - cause device to interrupt */
-
-#define CU_STATUS_MASK 0x00C0
-#define RU_STATUS_MASK 0x003C
-
-#define RU_STATUS_IDLE (0<<2)
-#define RU_STATUS_SUS (1<<2)
-#define RU_STATUS_NORES (2<<2)
-#define RU_STATUS_READY (4<<2)
-#define RU_STATUS_NO_RBDS_SUS ((1<<2)|(8<<2))
+#define RUC_NOP 0x0000
+#define RUC_START 0x0001
+#define RUC_RESUME 0x0002
+#define RUC_ABORT 0x0004
+#define RUC_ADDR_LOAD 0x0006 /* (seems not to clear on acceptance) */
+#define RUC_RESUMENR 0x0007
+
+#define CU_CMD_MASK 0x00f0
+#define RU_CMD_MASK 0x0007
+
+#define SCB_M 0x0100 /* 0 = enable interrupt, 1 = disable */
+#define SCB_SWI 0x0200 /* 1 - cause device to interrupt */
+
+#define CU_STATUS_MASK 0x00C0
+#define RU_STATUS_MASK 0x003C
+
+#define RU_STATUS_IDLE (0<<2)
+#define RU_STATUS_SUS (1<<2)
+#define RU_STATUS_NORES (2<<2)
+#define RU_STATUS_READY (4<<2)
+#define RU_STATUS_NO_RBDS_SUS ((1<<2)|(8<<2))
#define RU_STATUS_NO_RBDS_NORES ((2<<2)|(8<<2))
#define RU_STATUS_NO_RBDS_READY ((4<<2)|(8<<2))
@@ -138,27 +139,27 @@ struct RxFD {
};
#define RFD_STATUS_C 0x8000 /* completion of received frame */
-#define RFD_STATUS_OK 0x2000 /* frame received with no errors */
-
-#define RFD_CONTROL_EL 0x8000 /* 1=last RFD in RFA */
-#define RFD_CONTROL_S 0x4000 /* 1=suspend RU after receiving frame */
-#define RFD_CONTROL_H 0x0010 /* 1=RFD is a header RFD */
-#define RFD_CONTROL_SF 0x0008 /* 0=simplified, 1=flexible mode */
-
-#define RFD_COUNT_MASK 0x3fff
-#define RFD_COUNT_F 0x4000
-#define RFD_COUNT_EOF 0x8000
-
-#define RFD_RX_CRC 0x0800 /* crc error */
-#define RFD_RX_ALIGNMENT 0x0400 /* alignment error */
-#define RFD_RX_RESOURCE 0x0200 /* out of space, no resources */
-#define RFD_RX_DMA_OVER 0x0100 /* DMA overrun */
-#define RFD_RX_SHORT 0x0080 /* short frame error */
-#define RFD_RX_LENGTH 0x0020
-#define RFD_RX_ERROR 0x0010 /* receive error */
-#define RFD_RX_NO_ADR_MATCH 0x0004 /* no address match */
-#define RFD_RX_IA_MATCH 0x0002 /* individual address does not match */
-#define RFD_RX_TCO 0x0001 /* TCO indication */
+#define RFD_STATUS_OK 0x2000 /* frame received with no errors */
+
+#define RFD_CONTROL_EL 0x8000 /* 1=last RFD in RFA */
+#define RFD_CONTROL_S 0x4000 /* 1=suspend RU after receiving frame */
+#define RFD_CONTROL_H 0x0010 /* 1=RFD is a header RFD */
+#define RFD_CONTROL_SF 0x0008 /* 0=simplified, 1=flexible mode */
+
+#define RFD_COUNT_MASK 0x3fff
+#define RFD_COUNT_F 0x4000
+#define RFD_COUNT_EOF 0x8000
+
+#define RFD_RX_CRC 0x0800 /* crc error */
+#define RFD_RX_ALIGNMENT 0x0400 /* alignment error */
+#define RFD_RX_RESOURCE 0x0200 /* out of space, no resources */
+#define RFD_RX_DMA_OVER 0x0100 /* DMA overrun */
+#define RFD_RX_SHORT 0x0080 /* short frame error */
+#define RFD_RX_LENGTH 0x0020
+#define RFD_RX_ERROR 0x0010 /* receive error */
+#define RFD_RX_NO_ADR_MATCH 0x0004 /* no address match */
+#define RFD_RX_IA_MATCH 0x0002 /* individual address does not match */
+#define RFD_RX_TCO 0x0001 /* TCO indication */
/* Transmit frame descriptors
*/
@@ -176,45 +177,45 @@ struct TxFD { /* Transmit frame descriptor set. */
};
#define TxCB_CMD_TRANSMIT 0x0004 /* transmit command */
-#define TxCB_CMD_SF 0x0008 /* 0=simplified, 1=flexible mode */
-#define TxCB_CMD_NC 0x0010 /* 0=CRC insert by controller */
-#define TxCB_CMD_I 0x2000 /* generate interrupt on completion */
-#define TxCB_CMD_S 0x4000 /* suspend on completion */
-#define TxCB_CMD_EL 0x8000 /* last command block in CBL */
+#define TxCB_CMD_SF 0x0008 /* 0=simplified, 1=flexible mode */
+#define TxCB_CMD_NC 0x0010 /* 0=CRC insert by controller */
+#define TxCB_CMD_I 0x2000 /* generate interrupt on completion */
+#define TxCB_CMD_S 0x4000 /* suspend on completion */
+#define TxCB_CMD_EL 0x8000 /* last command block in CBL */
-#define TxCB_COUNT_MASK 0x3fff
-#define TxCB_COUNT_EOF 0x8000
+#define TxCB_COUNT_MASK 0x3fff
+#define TxCB_COUNT_EOF 0x8000
/* The Speedo3 Rx and Tx frame/buffer descriptors.
*/
struct descriptor { /* A generic descriptor. */
volatile u16 status;
volatile u16 command;
- volatile u32 link; /* struct descriptor * */
+ volatile u32 link; /* struct descriptor * */
unsigned char params[0];
};
-#define CFG_CMD_EL 0x8000
-#define CFG_CMD_SUSPEND 0x4000
-#define CFG_CMD_INT 0x2000
-#define CFG_CMD_IAS 0x0001 /* individual address setup */
-#define CFG_CMD_CONFIGURE 0x0002 /* configure */
+#define CFG_CMD_EL 0x8000
+#define CFG_CMD_SUSPEND 0x4000
+#define CFG_CMD_INT 0x2000
+#define CFG_CMD_IAS 0x0001 /* individual address setup */
+#define CFG_CMD_CONFIGURE 0x0002 /* configure */
-#define CFG_STATUS_C 0x8000
-#define CFG_STATUS_OK 0x2000
+#define CFG_STATUS_C 0x8000
+#define CFG_STATUS_OK 0x2000
/* Misc.
*/
-#define NUM_RX_DESC PKTBUFSRX
-#define NUM_TX_DESC 1 /* Number of TX descriptors */
+#define NUM_RX_DESC PKTBUFSRX
+#define NUM_TX_DESC 1 /* Number of TX descriptors */
#define TOUT_LOOP 1000000
#define ETH_ALEN 6
-static struct RxFD rx_ring[NUM_RX_DESC]; /* RX descriptor ring */
-static struct TxFD tx_ring[NUM_TX_DESC]; /* TX descriptor ring */
+static struct RxFD rx_ring[NUM_RX_DESC]; /* RX descriptor ring */
+static struct TxFD tx_ring[NUM_TX_DESC]; /* TX descriptor ring */
static int rx_next; /* RX descriptor ring pointer */
static int tx_next; /* TX descriptor ring pointer */
static int tx_threshold;
@@ -271,8 +272,124 @@ static inline void OUTL (struct eth_device *dev, int command, u_long addr)
*(volatile u32 *) ((addr + dev->iobase)) = cpu_to_le32 (command);
}
- /* Wait for the chip get the command.
- */
+#if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)
+static inline int INL (struct eth_device *dev, u_long addr)
+{
+ return le32_to_cpu (*(volatile u32 *) (addr + dev->iobase));
+}
+
+static int get_phyreg (struct eth_device *dev, unsigned char addr,
+ unsigned char reg, unsigned short *value)
+{
+ int cmd;
+ int timeout = 50;
+
+ /* read requested data */
+ cmd = (2 << 26) | ((addr & 0x1f) << 21) | ((reg & 0x1f) << 16);
+ OUTL (dev, cmd, SCBCtrlMDI);
+
+ do {
+ udelay(1000);
+ cmd = INL (dev, SCBCtrlMDI);
+ } while (!(cmd & (1 << 28)) && (--timeout));
+
+ if (timeout == 0)
+ return -1;
+
+ *value = (unsigned short) (cmd & 0xffff);
+
+ return 0;
+}
+
+static int set_phyreg (struct eth_device *dev, unsigned char addr,
+ unsigned char reg, unsigned short value)
+{
+ int cmd;
+ int timeout = 50;
+
+ /* write requested data */
+ cmd = (1 << 26) | ((addr & 0x1f) << 21) | ((reg & 0x1f) << 16);
+ OUTL (dev, cmd | value, SCBCtrlMDI);
+
+ while (!(INL (dev, SCBCtrlMDI) & (1 << 28)) && (--timeout))
+ udelay(1000);
+
+ if (timeout == 0)
+ return -1;
+
+ return 0;
+}
+
+/* Check if given phyaddr is valid, i.e. there is a PHY connected.
+ * Do this by checking model value field from ID2 register.
+ */
+static struct eth_device* verify_phyaddr (char *devname, unsigned char addr)
+{
+ struct eth_device *dev;
+ unsigned short value;
+ unsigned char model;
+
+ dev = eth_get_dev_by_name(devname);
+ if (dev == NULL) {
+ printf("%s: no such device\n", devname);
+ return NULL;
+ }
+
+ /* read id2 register */
+ if (get_phyreg(dev, addr, PHY_PHYIDR2, &value) != 0) {
+ printf("%s: mii read timeout!\n", devname);
+ return NULL;
+ }
+
+ /* get model */
+ model = (unsigned char)((value >> 4) & 0x003f);
+
+ if (model == 0) {
+ printf("%s: no PHY at address %d\n", devname, addr);
+ return NULL;
+ }
+
+ return dev;
+}
+
+static int eepro100_miiphy_read (char *devname, unsigned char addr,
+ unsigned char reg, unsigned short *value)
+{
+ struct eth_device *dev;
+
+ dev = verify_phyaddr(devname, addr);
+ if (dev == NULL)
+ return -1;
+
+ if (get_phyreg(dev, addr, reg, value) != 0) {
+ printf("%s: mii read timeout!\n", devname);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int eepro100_miiphy_write (char *devname, unsigned char addr,
+ unsigned char reg, unsigned short value)
+{
+ struct eth_device *dev;
+
+ dev = verify_phyaddr(devname, addr);
+ if (dev == NULL)
+ return -1;
+
+ if (set_phyreg(dev, addr, reg, value) != 0) {
+ printf("%s: mii write timeout!\n", devname);
+ return -1;
+ }
+
+ return 0;
+}
+
+#endif /* defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII) */
+
+/* Wait for the chip get the command.
+*/
static int wait_for_eepro100 (struct eth_device *dev)
{
int i;
@@ -345,6 +462,12 @@ int eepro100_initialize (bd_t * bis)
eth_register (dev);
+#if defined (CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)
+ /* register mii command access routines */
+ miiphy_register(dev->name,
+ eepro100_miiphy_read, eepro100_miiphy_write);
+#endif
+
card_number++;
/* Set the latency timer for value.
@@ -723,12 +846,12 @@ int eepro100_write_eeprom (struct eth_device* dev, int location, int addr_len, u
OUTW(dev, EE_ENB | dataval, SCBeeprom);
udelay(1);
- datalong = datalong << 1; /* Adjust significant data bit*/
+ datalong = datalong << 1; /* Adjust significant data bit*/
}
/* Finish up command (toggle CS) */
OUTW(dev, EE_ENB & ~EE_CS, SCBeeprom);
- udelay(1); /* delay for more than 250 ns */
+ udelay(1); /* delay for more than 250 ns */
OUTW(dev, EE_ENB, SCBeeprom);
/* Wait for programming ready (D0 = 1) */
diff --git a/drivers/i8042.c b/drivers/i8042.c
index e21978d..5f273a2 100644
--- a/drivers/i8042.c
+++ b/drivers/i8042.c
@@ -29,6 +29,14 @@
#ifdef CONFIG_I8042_KBD
+#ifdef CONFIG_USE_CPCIDVI
+extern u8 gt_cpcidvi_in8(u32 offset);
+extern void gt_cpcidvi_out8(u32 offset, u8 data);
+
+#define in8(a) gt_cpcidvi_in8(a)
+#define out8(a, b) gt_cpcidvi_out8(a,b)
+#endif
+
#include <i8042.h>
/* defines */
@@ -318,6 +326,13 @@ int i8042_kbd_init (void)
int keymap, try;
char *penv;
+#ifdef CONFIG_USE_CPCIDVI
+ if ((penv = getenv ("console")) != NULL) {
+ if (strncmp (penv, "serial", 7) == 0) {
+ return -1;
+ }
+ }
+#endif
/* Init keyboard device (default US layout) */
keymap = KBD_US;
if ((penv = getenv ("keymap")) != NULL)
@@ -633,7 +648,11 @@ static int kbd_reset (void)
if (kbd_input_empty() == 0)
return -1;
+#ifdef CONFIG_USE_CPCIDVI
+ out8 (I8042_COMMAND_REG, 0x60);
+#else
out8 (I8042_DATA_REG, 0x60);
+#endif
if (kbd_input_empty() == 0)
return -1;
diff --git a/drivers/lan91c96.h b/drivers/lan91c96.h
index 5c2afce..b7d7455 100644
--- a/drivers/lan91c96.h
+++ b/drivers/lan91c96.h
@@ -78,17 +78,27 @@ typedef unsigned long int dword;
#ifdef CONFIG_PXA250
-#define SMC_inl(r) (*((volatile dword *)(SMC_BASE_ADDRESS+( r * 4 ))))
-#define SMC_inw(r) (*((volatile word *)(SMC_BASE_ADDRESS+( r * 4 ))))
-#define SMC_inb(p) ({ \
- unsigned int __p = (unsigned int)(SMC_BASE_ADDRESS + (p * 4)); \
- unsigned int __v = *(volatile unsigned short *)((__p) & ~1); \
+#ifdef CONFIG_LUBBOCK
+#define SMC_IO_SHIFT 2
+#undef USE_32_BIT
+
+#else
+#define SMC_IO_SHIFT 0
+#endif
+
+#define SMCREG(r) (SMC_BASE_ADDRESS+((r)<<SMC_IO_SHIFT))
+
+#define SMC_inl(r) (*((volatile dword *)SMCREG(r)))
+#define SMC_inw(r) (*((volatile word *)SMCREG(r)))
+#define SMC_inb(p) ({ \
+ unsigned int __p = p; \
+ unsigned int __v = SMC_inw(__p & ~1); \
if (__p & 1) __v >>= 8; \
else __v &= 0xff; \
__v; })
-#define SMC_outl(d,r) (*((volatile dword *)(SMC_BASE_ADDRESS+(r * 4))) = d)
-#define SMC_outw(d,r) (*((volatile word *)(SMC_BASE_ADDRESS+(r * 4))) = d)
+#define SMC_outl(d,r) (*((volatile dword *)SMCREG(r)) = d)
+#define SMC_outw(d,r) (*((volatile word *)SMCREG(r)) = d)
#define SMC_outb(d,r) ({ word __d = (byte)(d); \
word __w = SMC_inw((r)&~1); \
__w &= ((r)&1) ? 0x00FF : 0xFF00; \
diff --git a/drivers/nand/diskonchip.c b/drivers/nand/diskonchip.c
index b421d4c..07e2549 100644
--- a/drivers/nand/diskonchip.c
+++ b/drivers/nand/diskonchip.c
@@ -19,6 +19,8 @@
* $Id: diskonchip.c,v 1.45 2005/01/05 18:05:14 dwmw2 Exp $
*/
+#include <common.h>
+#ifdef CONFIG_NEW_NAND_CODE
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/sched.h>
@@ -1780,3 +1782,4 @@ module_exit(cleanup_nanddoc);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
MODULE_DESCRIPTION("M-Systems DiskOnChip 2000, Millennium and Millennium Plus device driver\n");
+#endif /* CONFIG_NEW_NAND_CODE */
diff --git a/drivers/nand/nand.c b/drivers/nand/nand.c
index d187c89..bc85005 100644
--- a/drivers/nand/nand.c
+++ b/drivers/nand/nand.c
@@ -23,6 +23,7 @@
#include <common.h>
+#ifdef CONFIG_NEW_NAND_CODE
#if (CONFIG_COMMANDS & CFG_CMD_NAND)
#include <nand.h>
@@ -46,12 +47,12 @@ static void nand_init_chip(struct mtd_info *mtd, struct nand_chip *nand,
{
mtd->priv = nand;
- nand->IO_ADDR_R = nand->IO_ADDR_W = base_addr;
+ nand->IO_ADDR_R = nand->IO_ADDR_W = (void __iomem *)base_addr;
board_nand_init(nand);
if (nand_scan(mtd, 1) == 0) {
if (!mtd->name)
- mtd->name = default_nand_name;
+ mtd->name = (char *)default_nand_name;
} else
mtd->name = NULL;
@@ -60,12 +61,16 @@ static void nand_init_chip(struct mtd_info *mtd, struct nand_chip *nand,
void nand_init(void)
{
int i;
-
+ unsigned int size = 0;
for (i = 0; i < CFG_MAX_NAND_DEVICE; i++) {
nand_init_chip(&nand_info[i], &nand_chip[i], base_address[i]);
+ size += nand_info[i].size;
if (nand_curr_device == -1)
nand_curr_device = i;
- }
+}
+ printf("%lu MiB\n", size / (1024 * 1024));
}
#endif
+#endif /* CONFIG_NEW_NAND_CODE */
+
diff --git a/drivers/nand/nand_base.c b/drivers/nand/nand_base.c
index 9ec5af9..b039c3c 100644
--- a/drivers/nand/nand_base.c
+++ b/drivers/nand/nand_base.c
@@ -71,6 +71,7 @@
#endif
#include <common.h>
+#ifdef CONFIG_NEW_NAND_CODE
#if (CONFIG_COMMANDS & CFG_CMD_NAND)
@@ -847,11 +848,13 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *this, int state)
else
this->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
- reset_timer_masked();
+ reset_timer();
while (1) {
- if (get_timer_masked() > timeo)
+ if (get_timer(0) > timeo) {
+ printf("Timeout!");
return 0;
+ }
if (this->dev_ready) {
if (this->dev_ready(mtd))
@@ -862,6 +865,10 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *this, int state)
}
}
+ /* XXX nand device 1 on dave (PPChameleonEVB) needs more time */
+ reset_timer();
+ while (get_timer(0) < 10);
+
return this->read_byte(mtd);
}
#endif
@@ -2393,9 +2400,6 @@ int nand_scan (struct mtd_info *mtd, int maxchips)
if (nand_manuf_ids[j].id == nand_maf_id)
break;
}
- printk (KERN_INFO "NAND device: Manufacturer ID:"
- " 0x%02x, Chip ID: 0x%02x (%s %s)\n", nand_maf_id, nand_dev_id,
- nand_manuf_ids[j].name , nand_flash_ids[i].name);
break;
}
@@ -2656,3 +2660,5 @@ void nand_release (struct mtd_info *mtd)
}
#endif
+#endif /* CONFIG_NEW_NAND_CODE */
+
diff --git a/drivers/nand/nand_bbt.c b/drivers/nand/nand_bbt.c
index dfa88a3..f481308 100644
--- a/drivers/nand/nand_bbt.c
+++ b/drivers/nand/nand_bbt.c
@@ -54,6 +54,7 @@
#include <common.h>
+#ifdef CONFIG_NEW_NAND_CODE
#if (CONFIG_COMMANDS & CFG_CMD_NAND)
#include <malloc.h>
@@ -261,8 +262,6 @@ static void create_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc
loff_t from;
size_t readlen, ooblen;
- printk (KERN_INFO "Scanning device for bad blocks\n");
-
if (bd->options & NAND_BBT_SCANALLPAGES)
len = 1 << (this->bbt_erase_shift - this->page_shift);
else {
@@ -298,8 +297,6 @@ static void create_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc
for (j = 0; j < len; j++) {
if (check_pattern (&buf[j * scanlen], scanlen, mtd->oobblock, bd)) {
this->bbt[i >> 3] |= 0x03 << (i & 0x6);
- printk (KERN_WARNING "Bad eraseblock %d at 0x%08x\n",
- i >> 1, (unsigned int) from);
break;
}
}
@@ -1054,3 +1051,5 @@ int nand_isbad_bbt (struct mtd_info *mtd, loff_t offs, int allowbbt)
}
#endif
+#endif /* CONFIG_NEW_NAND_CODE */
+
diff --git a/drivers/nand/nand_ecc.c b/drivers/nand/nand_ecc.c
index 6e11c22..4e610c1 100644
--- a/drivers/nand/nand_ecc.c
+++ b/drivers/nand/nand_ecc.c
@@ -37,8 +37,10 @@
#include <common.h>
+#ifdef CONFIG_NEW_NAND_CODE
#if (CONFIG_COMMANDS & CFG_CMD_NAND)
+#include<linux/mtd/mtd.h>
/*
* Pre-calculated 256-way 1 byte column parity
*/
@@ -241,3 +243,5 @@ int nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_cha
}
#endif /* CONFIG_COMMANDS & CFG_CMD_NAND */
+#endif /* CONFIG_NEW_NAND_CODE */
+
diff --git a/drivers/nand/nand_ids.c b/drivers/nand/nand_ids.c
index 39882cc..d355326 100644
--- a/drivers/nand/nand_ids.c
+++ b/drivers/nand/nand_ids.c
@@ -10,8 +10,10 @@
* published by the Free Software Foundation.
*
*/
+
#include <common.h>
+#ifdef CONFIG_NEW_NAND_CODE
#if (CONFIG_COMMANDS & CFG_CMD_NAND)
#include <linux/mtd/nand.h>
@@ -125,3 +127,5 @@ struct nand_manufacturers nand_manuf_ids[] = {
{0x0, "Unknown"}
};
#endif
+#endif /* CONFIG_NEW_NAND_CODE */
+
diff --git a/drivers/natsemi.c b/drivers/natsemi.c
index 1c1b9a0..b009db6 100644
--- a/drivers/natsemi.c
+++ b/drivers/natsemi.c
@@ -756,6 +756,7 @@ natsemi_send(struct eth_device *dev, volatile void *packet, int length)
{
u32 i, status = 0;
u32 tx_status = 0;
+ vu_long *res = (vu_long *)&tx_status;
/* Stop the transmitter */
OUTL(dev, TxOff, ChipCmd);
@@ -781,7 +782,7 @@ natsemi_send(struct eth_device *dev, volatile void *packet, int length)
OUTL(dev, TxOn, ChipCmd);
for (i = 0;
- ((vu_long)tx_status = le32_to_cpu(txd.cmdsts)) & DescOwn;
+ (*res = le32_to_cpu(txd.cmdsts)) & DescOwn;
i++) {
if (i >= TOUT_LOOP) {
printf
diff --git a/drivers/netconsole.c b/drivers/netconsole.c
index 9cf6cd6..9a0a24f 100644
--- a/drivers/netconsole.c
+++ b/drivers/netconsole.c
@@ -29,10 +29,6 @@
#include <devices.h>
#include <net.h>
-#ifndef CONFIG_NET_MULTI
-#error define CONFIG_NET_MULTI to use netconsole
-#endif
-
static char input_buffer[512];
static int input_size = 0; /* char count in input buffer */
static int input_offset = 0; /* offset to valid chars in input buffer */
diff --git a/drivers/ns7520_eth.c b/drivers/ns7520_eth.c
new file mode 100644
index 0000000..a5a20df
--- /dev/null
+++ b/drivers/ns7520_eth.c
@@ -0,0 +1,859 @@
+/***********************************************************************
+ *
+ * Copyright (C) 2005 by Videon Central, Inc.
+ *
+ * $Id$
+ * @Author: Arthur Shipkowski
+ * @Descr: Ethernet driver for the NS7520. Uses polled Ethernet, like
+ * the older netarmeth driver. Note that attempting to filter
+ * broadcast and multicast out in the SAFR register will cause
+ * bad things due to released errata.
+ * @References: [1] NS7520 Hardware Reference, December 2003
+ * [2] Intel LXT971 Datasheet #249414 Rev. 02
+ *
+ ***********************************************************************/
+
+#include <common.h>
+
+#if defined(CONFIG_DRIVER_NS7520_ETHERNET)
+
+#include <net.h> /* NetSendPacket */
+#include <asm/arch/netarm_registers.h>
+#include <asm/arch/netarm_dma_module.h>
+
+#include "ns7520_eth.h" /* for Ethernet and PHY */
+
+/**
+ * Send an error message to the terminal.
+ */
+#define ERROR(x) \
+do { \
+ char *__foo = strrchr(__FILE__, '/'); \
+ \
+ printf("%s: %d: %s(): ", (__foo == NULL ? __FILE__ : (__foo + 1)), \
+ __LINE__, __FUNCTION__); \
+ printf x; printf("\n"); \
+} while (0);
+
+/* some definition to make transistion to linux easier */
+
+#define NS7520_DRIVER_NAME "eth"
+#define KERN_WARNING "Warning:"
+#define KERN_ERR "Error:"
+#define KERN_INFO "Info:"
+
+#if 1
+# define DEBUG
+#endif
+
+#ifdef DEBUG
+# define printk printf
+
+# define DEBUG_INIT 0x0001
+# define DEBUG_MINOR 0x0002
+# define DEBUG_RX 0x0004
+# define DEBUG_TX 0x0008
+# define DEBUG_INT 0x0010
+# define DEBUG_POLL 0x0020
+# define DEBUG_LINK 0x0040
+# define DEBUG_MII 0x0100
+# define DEBUG_MII_LOW 0x0200
+# define DEBUG_MEM 0x0400
+# define DEBUG_ERROR 0x4000
+# define DEBUG_ERROR_CRIT 0x8000
+
+static int nDebugLvl = DEBUG_ERROR_CRIT;
+
+# define DEBUG_ARGS0( FLG, a0 ) if( ( nDebugLvl & (FLG) ) == (FLG) ) \
+ printf("%s: " a0, __FUNCTION__, 0, 0, 0, 0, 0, 0 )
+# define DEBUG_ARGS1( FLG, a0, a1 ) if( ( nDebugLvl & (FLG) ) == (FLG)) \
+ printf("%s: " a0, __FUNCTION__, (int)(a1), 0, 0, 0, 0, 0 )
+# define DEBUG_ARGS2( FLG, a0, a1, a2 ) if( (nDebugLvl & (FLG)) ==(FLG))\
+ printf("%s: " a0, __FUNCTION__, (int)(a1), (int)(a2), 0, 0,0,0 )
+# define DEBUG_ARGS3( FLG, a0, a1, a2, a3 ) if((nDebugLvl &(FLG))==(FLG))\
+ printf("%s: "a0,__FUNCTION__,(int)(a1),(int)(a2),(int)(a3),0,0,0)
+# define DEBUG_FN( FLG ) if( (nDebugLvl & (FLG)) == (FLG) ) \
+ printf("\r%s:line %d\n", (int)__FUNCTION__, __LINE__, 0,0,0,0);
+# define ASSERT( expr, func ) if( !( expr ) ) { \
+ printf( "Assertion failed! %s:line %d %s\n", \
+ (int)__FUNCTION__,__LINE__,(int)(#expr),0,0,0); \
+ func }
+#else /* DEBUG */
+# define printk(...)
+# define DEBUG_ARGS0( FLG, a0 )
+# define DEBUG_ARGS1( FLG, a0, a1 )
+# define DEBUG_ARGS2( FLG, a0, a1, a2 )
+# define DEBUG_ARGS3( FLG, a0, a1, a2, a3 )
+# define DEBUG_FN( n )
+# define ASSERT(expr, func)
+#endif /* DEBUG */
+
+#define NS7520_MII_NEG_DELAY (5*CFG_HZ) /* in s */
+#define TX_TIMEOUT (5*CFG_HZ) /* in s */
+#define RX_STALL_WORKAROUND_CNT 100
+
+static int ns7520_eth_reset(void);
+
+static void ns7520_link_auto_negotiate(void);
+static void ns7520_link_update_egcr(void);
+static void ns7520_link_print_changed(void);
+
+/* the PHY stuff */
+
+static char ns7520_mii_identify_phy(void);
+static unsigned short ns7520_mii_read(unsigned short uiRegister);
+static void ns7520_mii_write(unsigned short uiRegister,
+ unsigned short uiData);
+static unsigned int ns7520_mii_get_clock_divisor(unsigned int
+ unMaxMDIOClk);
+static unsigned int ns7520_mii_poll_busy(void);
+
+static unsigned int nPhyMaxMdioClock = PHY_MDIO_MAX_CLK;
+static unsigned int uiLastLinkStatus;
+static PhyType phyDetected = PHY_NONE;
+
+/***********************************************************************
+ * @Function: eth_init
+ * @Return: -1 on failure otherwise 0
+ * @Descr: Initializes the ethernet engine and uses either FS Forth's default
+ * MAC addr or the one in environment
+ ***********************************************************************/
+
+int eth_init(bd_t * pbis)
+{
+ unsigned char aucMACAddr[6];
+ char *pcTmp = getenv("ethaddr");
+ char *pcEnd;
+ int i;
+
+ DEBUG_FN(DEBUG_INIT);
+
+ /* no need to check for hardware */
+
+ if (!ns7520_eth_reset())
+ return -1;
+
+ if (NULL == pcTmp)
+ return -1;
+
+ for (i = 0; i < 6; i++) {
+ aucMACAddr[i] =
+ pcTmp ? simple_strtoul(pcTmp, &pcEnd, 16) : 0;
+ pcTmp = (*pcTmp) ? pcEnd + 1 : pcEnd;
+ }
+
+ /* configure ethernet address */
+
+ *get_eth_reg_addr(NS7520_ETH_SA1) =
+ aucMACAddr[5] << 8 | aucMACAddr[4];
+ *get_eth_reg_addr(NS7520_ETH_SA2) =
+ aucMACAddr[3] << 8 | aucMACAddr[2];
+ *get_eth_reg_addr(NS7520_ETH_SA3) =
+ aucMACAddr[1] << 8 | aucMACAddr[0];
+
+ /* enable hardware */
+
+ *get_eth_reg_addr(NS7520_ETH_MAC1) = NS7520_ETH_MAC1_RXEN;
+ *get_eth_reg_addr(NS7520_ETH_SUPP) = NS7520_ETH_SUPP_JABBER;
+ *get_eth_reg_addr(NS7520_ETH_MAC1) = NS7520_ETH_MAC1_RXEN;
+
+ /* the linux kernel may give packets < 60 bytes, for example arp */
+ *get_eth_reg_addr(NS7520_ETH_MAC2) = NS7520_ETH_MAC2_CRCEN |
+ NS7520_ETH_MAC2_PADEN | NS7520_ETH_MAC2_HUGE;
+
+ /* Broadcast/multicast allowed; if you don't set this even unicast chokes */
+ /* Based on NS7520 errata documentation */
+ *get_eth_reg_addr(NS7520_ETH_SAFR) =
+ NS7520_ETH_SAFR_BROAD | NS7520_ETH_SAFR_PRM;
+
+ /* enable receive and transmit FIFO, use 10/100 Mbps MII */
+ *get_eth_reg_addr(NS7520_ETH_EGCR) |=
+ NS7520_ETH_EGCR_ETXWM_75 |
+ NS7520_ETH_EGCR_ERX |
+ NS7520_ETH_EGCR_ERXREG |
+ NS7520_ETH_EGCR_ERXBR | NS7520_ETH_EGCR_ETX;
+
+ return 0;
+}
+
+/***********************************************************************
+ * @Function: eth_send
+ * @Return: -1 on timeout otherwise 1
+ * @Descr: sends one frame by DMA
+ ***********************************************************************/
+
+int eth_send(volatile void *pPacket, int nLen)
+{
+ int i, length32, retval = 1;
+ char *pa;
+ unsigned int *pa32, lastp = 0, rest;
+ unsigned int status;
+
+ pa = (char *) pPacket;
+ pa32 = (unsigned int *) pPacket;
+ length32 = nLen / 4;
+ rest = nLen % 4;
+
+ /* make sure there's no garbage in the last word */
+ switch (rest) {
+ case 0:
+ lastp = pa32[length32 - 1];
+ length32--;
+ break;
+ case 1:
+ lastp = pa32[length32] & 0x000000ff;
+ break;
+ case 2:
+ lastp = pa32[length32] & 0x0000ffff;
+ break;
+ case 3:
+ lastp = pa32[length32] & 0x00ffffff;
+ break;
+ }
+
+ while (((*get_eth_reg_addr(NS7520_ETH_EGSR)) &
+ NS7520_ETH_EGSR_TXREGE)
+ == 0) {
+ }
+
+ /* write to the fifo */
+ for (i = 0; i < length32; i++)
+ *get_eth_reg_addr(NS7520_ETH_FIFO) = pa32[i];
+
+ /* the last word is written to an extra register, this
+ starts the transmission */
+ *get_eth_reg_addr(NS7520_ETH_FIFOL) = lastp;
+
+ /* Wait for it to be done */
+ while ((*get_eth_reg_addr(NS7520_ETH_EGSR) & NS7520_ETH_EGSR_TXBC)
+ == 0) {
+ }
+ status = (*get_eth_reg_addr(NS7520_ETH_ETSR));
+ *get_eth_reg_addr(NS7520_ETH_EGSR) = NS7520_ETH_EGSR_TXBC; /* Clear it now */
+
+ if (status & NS7520_ETH_ETSR_TXOK) {
+ retval = 0; /* We're OK! */
+ } else if (status & NS7520_ETH_ETSR_TXDEF) {
+ printf("Deferred, we'll see.\n");
+ retval = 0;
+ } else if (status & NS7520_ETH_ETSR_TXAL) {
+ printf("Late collision error, %d collisions.\n",
+ (*get_eth_reg_addr(NS7520_ETH_ETSR)) &
+ NS7520_ETH_ETSR_TXCOLC);
+ } else if (status & NS7520_ETH_ETSR_TXAEC) {
+ printf("Excessive collisions: %d\n",
+ (*get_eth_reg_addr(NS7520_ETH_ETSR)) &
+ NS7520_ETH_ETSR_TXCOLC);
+ } else if (status & NS7520_ETH_ETSR_TXAED) {
+ printf("Excessive deferral on xmit.\n");
+ } else if (status & NS7520_ETH_ETSR_TXAUR) {
+ printf("Packet underrun.\n");
+ } else if (status & NS7520_ETH_ETSR_TXAJ) {
+ printf("Jumbo packet error.\n");
+ } else {
+ printf("Error: Should never get here.\n");
+ }
+
+ return (retval);
+}
+
+/***********************************************************************
+ * @Function: eth_rx
+ * @Return: size of last frame in bytes or 0 if no frame available
+ * @Descr: gives one frame to U-Boot which has been copied by DMA engine already
+ * to NetRxPackets[ 0 ].
+ ***********************************************************************/
+
+int eth_rx(void)
+{
+ int i;
+ unsigned short rxlen;
+ unsigned short totrxlen = 0;
+ unsigned int *addr;
+ unsigned int rxstatus, lastrxlen;
+ char *pa;
+
+ /* If RXBR is 1, data block was received */
+ while (((*get_eth_reg_addr(NS7520_ETH_EGSR)) &
+ NS7520_ETH_EGSR_RXBR) == NS7520_ETH_EGSR_RXBR) {
+
+ /* get status register and the length of received block */
+ rxstatus = *get_eth_reg_addr(NS7520_ETH_ERSR);
+ rxlen = (rxstatus & NS7520_ETH_ERSR_RXSIZE) >> 16;
+
+ /* clear RXBR to make fifo available */
+ *get_eth_reg_addr(NS7520_ETH_EGSR) = NS7520_ETH_EGSR_RXBR;
+
+ if (rxstatus & NS7520_ETH_ERSR_ROVER) {
+ printf("Receive overrun, resetting FIFO.\n");
+ *get_eth_reg_addr(NS7520_ETH_EGCR) &=
+ ~NS7520_ETH_EGCR_ERX;
+ udelay(20);
+ *get_eth_reg_addr(NS7520_ETH_EGCR) |=
+ NS7520_ETH_EGCR_ERX;
+ }
+ if (rxlen == 0) {
+ printf("Nothing.\n");
+ return 0;
+ }
+
+ addr = (unsigned int *) NetRxPackets[0];
+ pa = (char *) NetRxPackets[0];
+
+ /* read the fifo */
+ for (i = 0; i < rxlen / 4; i++) {
+ *addr = *get_eth_reg_addr(NS7520_ETH_FIFO);
+ addr++;
+ }
+
+ if ((*get_eth_reg_addr(NS7520_ETH_EGSR)) &
+ NS7520_ETH_EGSR_RXREGR) {
+ /* RXFDB indicates wether the last word is 1,2,3 or 4 bytes long */
+ lastrxlen =
+ ((*get_eth_reg_addr(NS7520_ETH_EGSR)) &
+ NS7520_ETH_EGSR_RXFDB_MA) >> 28;
+ *addr = *get_eth_reg_addr(NS7520_ETH_FIFO);
+ switch (lastrxlen) {
+ case 1:
+ *addr &= 0xff000000;
+ break;
+ case 2:
+ *addr &= 0xffff0000;
+ break;
+ case 3:
+ *addr &= 0xffffff00;
+ break;
+ }
+ }
+
+ /* Pass the packet up to the protocol layers. */
+ NetReceive(NetRxPackets[0], rxlen - 4);
+ totrxlen += rxlen - 4;
+ }
+
+ return totrxlen;
+}
+
+/***********************************************************************
+ * @Function: eth_halt
+ * @Return: n/a
+ * @Descr: stops the ethernet engine
+ ***********************************************************************/
+
+void eth_halt(void)
+{
+ DEBUG_FN(DEBUG_INIT);
+
+ *get_eth_reg_addr(NS7520_ETH_MAC1) &= ~NS7520_ETH_MAC1_RXEN;
+ *get_eth_reg_addr(NS7520_ETH_EGCR) &= ~(NS7520_ETH_EGCR_ERX |
+ NS7520_ETH_EGCR_ERXDMA |
+ NS7520_ETH_EGCR_ERXREG |
+ NS7520_ETH_EGCR_ERXBR |
+ NS7520_ETH_EGCR_ETX |
+ NS7520_ETH_EGCR_ETXDMA);
+}
+
+/***********************************************************************
+ * @Function: ns7520_eth_reset
+ * @Return: 0 on failure otherwise 1
+ * @Descr: resets the ethernet interface and the PHY,
+ * performs auto negotiation or fixed modes
+ ***********************************************************************/
+
+static int ns7520_eth_reset(void)
+{
+ DEBUG_FN(DEBUG_MINOR);
+
+ /* Reset important registers */
+ *get_eth_reg_addr(NS7520_ETH_EGCR) = 0; /* Null it out! */
+ *get_eth_reg_addr(NS7520_ETH_MAC1) &= NS7520_ETH_MAC1_SRST;
+ *get_eth_reg_addr(NS7520_ETH_MAC2) = 0;
+ /* Reset MAC */
+ *get_eth_reg_addr(NS7520_ETH_EGCR) |= NS7520_ETH_EGCR_MAC_RES;
+ udelay(5);
+ *get_eth_reg_addr(NS7520_ETH_EGCR) &= ~NS7520_ETH_EGCR_MAC_RES;
+
+ /* reset and initialize PHY */
+
+ *get_eth_reg_addr(NS7520_ETH_MAC1) &= ~NS7520_ETH_MAC1_SRST;
+
+ /* we don't support hot plugging of PHY, therefore we don't reset
+ phyDetected and nPhyMaxMdioClock here. The risk is if the setting is
+ incorrect the first open
+ may detect the PHY correctly but succeding will fail
+ For reseting the PHY and identifying we have to use the standard
+ MDIO CLOCK value 2.5 MHz only after hardware reset
+ After having identified the PHY we will do faster */
+
+ *get_eth_reg_addr(NS7520_ETH_MCFG) =
+ ns7520_mii_get_clock_divisor(nPhyMaxMdioClock);
+
+ /* reset PHY */
+ ns7520_mii_write(PHY_COMMON_CTRL, PHY_COMMON_CTRL_RESET);
+ ns7520_mii_write(PHY_COMMON_CTRL, 0);
+
+ udelay(3000); /* [2] p.70 says at least 300us reset recovery time. */
+
+ /* MII clock has been setup to default, ns7520_mii_identify_phy should
+ work for all */
+
+ if (!ns7520_mii_identify_phy()) {
+ printk(KERN_ERR NS7520_DRIVER_NAME
+ ": Unsupported PHY, aborting\n");
+ return 0;
+ }
+
+ /* now take the highest MDIO clock possible after detection */
+ *get_eth_reg_addr(NS7520_ETH_MCFG) =
+ ns7520_mii_get_clock_divisor(nPhyMaxMdioClock);
+
+ /* PHY has been detected, so there can be no abort reason and we can
+ finish initializing ethernet */
+
+ uiLastLinkStatus = 0xff; /* undefined */
+
+ ns7520_link_auto_negotiate();
+
+ if (phyDetected == PHY_LXT971A)
+ /* set LED2 to link mode */
+ ns7520_mii_write(PHY_LXT971_LED_CFG,
+ (PHY_LXT971_LED_CFG_LINK_ACT <<
+ PHY_LXT971_LED_CFG_SHIFT_LED2) |
+ (PHY_LXT971_LED_CFG_TRANSMIT <<
+ PHY_LXT971_LED_CFG_SHIFT_LED1));
+
+ return 1;
+}
+
+/***********************************************************************
+ * @Function: ns7520_link_auto_negotiate
+ * @Return: void
+ * @Descr: performs auto-negotation of link.
+ ***********************************************************************/
+
+static void ns7520_link_auto_negotiate(void)
+{
+ unsigned long ulStartJiffies;
+ unsigned short uiStatus;
+
+ DEBUG_FN(DEBUG_LINK);
+
+ /* run auto-negotation */
+ /* define what we are capable of */
+ ns7520_mii_write(PHY_COMMON_AUTO_ADV,
+ PHY_COMMON_AUTO_ADV_100BTXFD |
+ PHY_COMMON_AUTO_ADV_100BTX |
+ PHY_COMMON_AUTO_ADV_10BTFD |
+ PHY_COMMON_AUTO_ADV_10BT |
+ PHY_COMMON_AUTO_ADV_802_3);
+ /* start auto-negotiation */
+ ns7520_mii_write(PHY_COMMON_CTRL,
+ PHY_COMMON_CTRL_AUTO_NEG |
+ PHY_COMMON_CTRL_RES_AUTO);
+
+ /* wait for completion */
+
+ ulStartJiffies = get_timer(0);
+ while (get_timer(0) < ulStartJiffies + NS7520_MII_NEG_DELAY) {
+ uiStatus = ns7520_mii_read(PHY_COMMON_STAT);
+ if ((uiStatus &
+ (PHY_COMMON_STAT_AN_COMP | PHY_COMMON_STAT_LNK_STAT))
+ ==
+ (PHY_COMMON_STAT_AN_COMP | PHY_COMMON_STAT_LNK_STAT)) {
+ /* lucky we are, auto-negotiation succeeded */
+ ns7520_link_print_changed();
+ ns7520_link_update_egcr();
+ return;
+ }
+ }
+
+ DEBUG_ARGS0(DEBUG_LINK, "auto-negotiation timed out\n");
+ /* ignore invalid link settings */
+}
+
+/***********************************************************************
+ * @Function: ns7520_link_update_egcr
+ * @Return: void
+ * @Descr: updates the EGCR and MAC2 link status after mode change or
+ * auto-negotation
+ ***********************************************************************/
+
+static void ns7520_link_update_egcr(void)
+{
+ unsigned int unEGCR;
+ unsigned int unMAC2;
+ unsigned int unIPGT;
+
+ DEBUG_FN(DEBUG_LINK);
+
+ unEGCR = *get_eth_reg_addr(NS7520_ETH_EGCR);
+ unMAC2 = *get_eth_reg_addr(NS7520_ETH_MAC2);
+ unIPGT =
+ *get_eth_reg_addr(NS7520_ETH_IPGT) & ~NS7520_ETH_IPGT_IPGT;
+
+ unEGCR &= ~NS7520_ETH_EGCR_EFULLD;
+ unMAC2 &= ~NS7520_ETH_MAC2_FULLD;
+ if ((uiLastLinkStatus & PHY_LXT971_STAT2_DUPLEX_MODE)
+ == PHY_LXT971_STAT2_DUPLEX_MODE) {
+ unEGCR |= NS7520_ETH_EGCR_EFULLD;
+ unMAC2 |= NS7520_ETH_MAC2_FULLD;
+ unIPGT |= 0x15; /* see [1] p. 167 */
+ } else
+ unIPGT |= 0x12; /* see [1] p. 167 */
+
+ *get_eth_reg_addr(NS7520_ETH_MAC2) = unMAC2;
+ *get_eth_reg_addr(NS7520_ETH_EGCR) = unEGCR;
+ *get_eth_reg_addr(NS7520_ETH_IPGT) = unIPGT;
+}
+
+/***********************************************************************
+ * @Function: ns7520_link_print_changed
+ * @Return: void
+ * @Descr: checks whether the link status has changed and if so prints
+ * the new mode
+ ***********************************************************************/
+
+static void ns7520_link_print_changed(void)
+{
+ unsigned short uiStatus;
+ unsigned short uiControl;
+
+ DEBUG_FN(DEBUG_LINK);
+
+ uiControl = ns7520_mii_read(PHY_COMMON_CTRL);
+
+ if ((uiControl & PHY_COMMON_CTRL_AUTO_NEG) ==
+ PHY_COMMON_CTRL_AUTO_NEG) {
+ /* PHY_COMMON_STAT_LNK_STAT is only set on autonegotiation */
+ uiStatus = ns7520_mii_read(PHY_COMMON_STAT);
+
+ if (!(uiStatus & PHY_COMMON_STAT_LNK_STAT)) {
+ printk(KERN_WARNING NS7520_DRIVER_NAME
+ ": link down\n");
+ /* @TODO Linux: carrier_off */
+ } else {
+ /* @TODO Linux: carrier_on */
+ if (phyDetected == PHY_LXT971A) {
+ uiStatus =
+ ns7520_mii_read(PHY_LXT971_STAT2);
+ uiStatus &=
+ (PHY_LXT971_STAT2_100BTX |
+ PHY_LXT971_STAT2_DUPLEX_MODE |
+ PHY_LXT971_STAT2_AUTO_NEG);
+
+ /* mask out all uninteresting parts */
+ }
+ /* other PHYs must store there link information in
+ uiStatus as PHY_LXT971 */
+ }
+ } else {
+ /* mode has been forced, so uiStatus should be the same as the
+ last link status, enforce printing */
+ uiStatus = uiLastLinkStatus;
+ uiLastLinkStatus = 0xff;
+ }
+
+ if (uiStatus != uiLastLinkStatus) {
+ /* save current link status */
+ uiLastLinkStatus = uiStatus;
+
+ /* print new link status */
+
+ printk(KERN_INFO NS7520_DRIVER_NAME
+ ": link mode %i Mbps %s duplex %s\n",
+ (uiStatus & PHY_LXT971_STAT2_100BTX) ? 100 : 10,
+ (uiStatus & PHY_LXT971_STAT2_DUPLEX_MODE) ? "full" :
+ "half",
+ (uiStatus & PHY_LXT971_STAT2_AUTO_NEG) ? "(auto)" :
+ "");
+ }
+}
+
+/***********************************************************************
+ * the MII low level stuff
+ ***********************************************************************/
+
+/***********************************************************************
+ * @Function: ns7520_mii_identify_phy
+ * @Return: 1 if supported PHY has been detected otherwise 0
+ * @Descr: checks for supported PHY and prints the IDs.
+ ***********************************************************************/
+
+static char ns7520_mii_identify_phy(void)
+{
+ unsigned short uiID1;
+ unsigned short uiID2;
+ unsigned char *szName;
+ char cRes = 0;
+
+ DEBUG_FN(DEBUG_MII);
+
+ phyDetected = (PhyType) uiID1 = ns7520_mii_read(PHY_COMMON_ID1);
+
+ switch (phyDetected) {
+ case PHY_LXT971A:
+ szName = "LXT971A";
+ uiID2 = ns7520_mii_read(PHY_COMMON_ID2);
+ nPhyMaxMdioClock = PHY_LXT971_MDIO_MAX_CLK;
+ cRes = 1;
+ break;
+ case PHY_NONE:
+ default:
+ /* in case uiID1 == 0 && uiID2 == 0 we may have the wrong
+ address or reset sets the wrong NS7520_ETH_MCFG_CLKS */
+
+ uiID2 = 0;
+ szName = "unknown";
+ nPhyMaxMdioClock = PHY_MDIO_MAX_CLK;
+ phyDetected = PHY_NONE;
+ }
+
+ printk(KERN_INFO NS7520_DRIVER_NAME
+ ": PHY (0x%x, 0x%x) = %s detected\n", uiID1, uiID2, szName);
+
+ return cRes;
+}
+
+/***********************************************************************
+ * @Function: ns7520_mii_read
+ * @Return: the data read from PHY register uiRegister
+ * @Descr: the data read may be invalid if timed out. If so, a message
+ * is printed but the invalid data is returned.
+ * The fixed device address is being used.
+ ***********************************************************************/
+
+static unsigned short ns7520_mii_read(unsigned short uiRegister)
+{
+ DEBUG_FN(DEBUG_MII_LOW);
+
+ /* write MII register to be read */
+ *get_eth_reg_addr(NS7520_ETH_MADR) =
+ CONFIG_PHY_ADDR << 8 | uiRegister;
+
+ *get_eth_reg_addr(NS7520_ETH_MCMD) = NS7520_ETH_MCMD_READ;
+
+ if (!ns7520_mii_poll_busy())
+ printk(KERN_WARNING NS7520_DRIVER_NAME
+ ": MII still busy in read\n");
+ /* continue to read */
+
+ *get_eth_reg_addr(NS7520_ETH_MCMD) = 0;
+
+ return (unsigned short) (*get_eth_reg_addr(NS7520_ETH_MRDD));
+}
+
+/***********************************************************************
+ * @Function: ns7520_mii_write
+ * @Return: nothing
+ * @Descr: writes the data to the PHY register. In case of a timeout,
+ * no special handling is performed but a message printed
+ * The fixed device address is being used.
+ ***********************************************************************/
+
+static void ns7520_mii_write(unsigned short uiRegister,
+ unsigned short uiData)
+{
+ DEBUG_FN(DEBUG_MII_LOW);
+
+ /* write MII register to be written */
+ *get_eth_reg_addr(NS7520_ETH_MADR) =
+ CONFIG_PHY_ADDR << 8 | uiRegister;
+
+ *get_eth_reg_addr(NS7520_ETH_MWTD) = uiData;
+
+ if (!ns7520_mii_poll_busy()) {
+ printf(KERN_WARNING NS7520_DRIVER_NAME
+ ": MII still busy in write\n");
+ }
+}
+
+/***********************************************************************
+ * @Function: ns7520_mii_get_clock_divisor
+ * @Return: the clock divisor that should be used in NS7520_ETH_MCFG_CLKS
+ * @Descr: if no clock divisor can be calculated for the
+ * current SYSCLK and the maximum MDIO Clock, a warning is printed
+ * and the greatest divisor is taken
+ ***********************************************************************/
+
+static unsigned int ns7520_mii_get_clock_divisor(unsigned int unMaxMDIOClk)
+{
+ struct {
+ unsigned int unSysClkDivisor;
+ unsigned int unClks; /* field for NS7520_ETH_MCFG_CLKS */
+ } PHYClockDivisors[] = {
+ {
+ 4, NS7520_ETH_MCFG_CLKS_4}, {
+ 6, NS7520_ETH_MCFG_CLKS_6}, {
+ 8, NS7520_ETH_MCFG_CLKS_8}, {
+ 10, NS7520_ETH_MCFG_CLKS_10}, {
+ 14, NS7520_ETH_MCFG_CLKS_14}, {
+ 20, NS7520_ETH_MCFG_CLKS_20}, {
+ 28, NS7520_ETH_MCFG_CLKS_28}
+ };
+
+ int nIndexSysClkDiv;
+ int nArraySize =
+ sizeof(PHYClockDivisors) / sizeof(PHYClockDivisors[0]);
+ unsigned int unClks = NS7520_ETH_MCFG_CLKS_28; /* defaults to
+ greatest div */
+
+ DEBUG_FN(DEBUG_INIT);
+
+ for (nIndexSysClkDiv = 0; nIndexSysClkDiv < nArraySize;
+ nIndexSysClkDiv++) {
+ /* find first sysclock divisor that isn't higher than 2.5 MHz
+ clock */
+ if (NETARM_XTAL_FREQ /
+ PHYClockDivisors[nIndexSysClkDiv].unSysClkDivisor <=
+ unMaxMDIOClk) {
+ unClks = PHYClockDivisors[nIndexSysClkDiv].unClks;
+ break;
+ }
+ }
+
+ DEBUG_ARGS2(DEBUG_INIT,
+ "Taking MDIO Clock bit mask 0x%0x for max clock %i\n",
+ unClks, unMaxMDIOClk);
+
+ /* return greatest divisor */
+ return unClks;
+}
+
+/***********************************************************************
+ * @Function: ns7520_mii_poll_busy
+ * @Return: 0 if timed out otherwise the remaing timeout
+ * @Descr: waits until the MII has completed a command or it times out
+ * code may be interrupted by hard interrupts.
+ * It is not checked what happens on multiple actions when
+ * the first is still being busy and we timeout.
+ ***********************************************************************/
+
+static unsigned int ns7520_mii_poll_busy(void)
+{
+ unsigned int unTimeout = 1000;
+
+ DEBUG_FN(DEBUG_MII_LOW);
+
+ while (((*get_eth_reg_addr(NS7520_ETH_MIND) & NS7520_ETH_MIND_BUSY)
+ == NS7520_ETH_MIND_BUSY) && unTimeout)
+ unTimeout--;
+
+ return unTimeout;
+}
+
+/* ----------------------------------------------------------------------------
+ * Net+ARM ethernet MII functionality.
+ */
+#if defined(CONFIG_MII)
+
+/**
+ * Maximum MII address we support
+ */
+#define MII_ADDRESS_MAX (31)
+
+/**
+ * Maximum MII register address we support
+ */
+#define MII_REGISTER_MAX (31)
+
+/**
+ * Ethernet MII interface return values for public functions.
+ */
+enum mii_status {
+ MII_STATUS_SUCCESS = 0,
+ MII_STATUS_FAILURE = 1,
+};
+
+/**
+ * Read a 16-bit value from an MII register.
+ */
+extern int ns7520_miiphy_read(char *devname, unsigned char const addr,
+ unsigned char const reg, unsigned short *const value)
+{
+ int ret = MII_STATUS_FAILURE;
+
+ /* Parameter checks */
+ if (addr > MII_ADDRESS_MAX) {
+ ERROR(("invalid addr, 0x%02X", addr));
+ goto miiphy_read_failed_0;
+ }
+
+ if (reg > MII_REGISTER_MAX) {
+ ERROR(("invalid reg, 0x%02X", reg));
+ goto miiphy_read_failed_0;
+ }
+
+ if (value == NULL) {
+ ERROR(("NULL value"));
+ goto miiphy_read_failed_0;
+ }
+
+ DEBUG_FN(DEBUG_MII_LOW);
+
+ /* write MII register to be read */
+ *get_eth_reg_addr(NS7520_ETH_MADR) = (addr << 8) | reg;
+
+ *get_eth_reg_addr(NS7520_ETH_MCMD) = NS7520_ETH_MCMD_READ;
+
+ if (!ns7520_mii_poll_busy())
+ printk(KERN_WARNING NS7520_DRIVER_NAME
+ ": MII still busy in read\n");
+ /* continue to read */
+
+ *get_eth_reg_addr(NS7520_ETH_MCMD) = 0;
+
+ *value = (*get_eth_reg_addr(NS7520_ETH_MRDD));
+ ret = MII_STATUS_SUCCESS;
+ /* Fall through */
+
+ miiphy_read_failed_0:
+ return (ret);
+}
+
+/**
+ * Write a 16-bit value to an MII register.
+ */
+extern int ns7520_miiphy_write(char *devname, unsigned char const addr,
+ unsigned char const reg, unsigned short const value)
+{
+ int ret = MII_STATUS_FAILURE;
+
+ /* Parameter checks */
+ if (addr > MII_ADDRESS_MAX) {
+ ERROR(("invalid addr, 0x%02X", addr));
+ goto miiphy_write_failed_0;
+ }
+
+ if (reg > MII_REGISTER_MAX) {
+ ERROR(("invalid reg, 0x%02X", reg));
+ goto miiphy_write_failed_0;
+ }
+
+ /* write MII register to be written */
+ *get_eth_reg_addr(NS7520_ETH_MADR) = (addr << 8) | reg;
+
+ *get_eth_reg_addr(NS7520_ETH_MWTD) = value;
+
+ if (!ns7520_mii_poll_busy()) {
+ printf(KERN_WARNING NS7520_DRIVER_NAME
+ ": MII still busy in write\n");
+ }
+
+ ret = MII_STATUS_SUCCESS;
+ /* Fall through */
+
+ miiphy_write_failed_0:
+ return (ret);
+}
+#endif /* defined(CONFIG_MII) */
+#endif /* CONFIG_DRIVER_NS7520_ETHERNET */
+
+int ns7520_miiphy_initialize(bd_t *bis)
+{
+#if defined(CONFIG_DRIVER_NS7520_ETHERNET)
+#if defined(CONFIG_MII)
+ miiphy_register("ns7520phy", ns7520_miiphy_read, ns7520_miiphy_write);
+#endif
+#endif
+ return 0;
+}
diff --git a/drivers/ns8382x.c b/drivers/ns8382x.c
index 281940b..976f86a 100644
--- a/drivers/ns8382x.c
+++ b/drivers/ns8382x.c
@@ -363,7 +363,7 @@ ns8382x_initialize(bd_t * bis)
/* get MAC address */
for (i = 0; i < 3; i++) {
u32 data;
- char *mac = &dev->enetaddr[i * 2];
+ char *mac = (char *)&dev->enetaddr[i * 2];
OUTL(dev, i * 2, RxFilterAddr);
data = INL(dev, RxFilterData);
@@ -745,7 +745,7 @@ static int
ns8382x_send(struct eth_device *dev, volatile void *packet, int length)
{
u32 i, status = 0;
- u32 tx_stat = 0;
+ vu_long tx_stat = 0;
/* Stop the transmitter */
OUTL(dev, TxOff, ChipCmd);
@@ -771,7 +771,7 @@ ns8382x_send(struct eth_device *dev, volatile void *packet, int length)
/* restart the transmitter */
OUTL(dev, TxOn, ChipCmd);
- for (i = 0; ((vu_long)tx_stat = le32_to_cpu(txd.cmdsts)) & DescOwn; i++) {
+ for (i = 0; (tx_stat = le32_to_cpu(txd.cmdsts)) & DescOwn; i++) {
if (i >= TOUT_LOOP) {
printf ("%s: tx error buffer not ready: txd.cmdsts %#X\n",
dev->name, tx_stat);
diff --git a/drivers/omap24xx_i2c.c b/drivers/omap24xx_i2c.c
index 383dfcb..7dab786 100644
--- a/drivers/omap24xx_i2c.c
+++ b/drivers/omap24xx_i2c.c
@@ -32,12 +32,16 @@
static void wait_for_bb (void);
static u16 wait_for_pin (void);
-void flush_fifo(void);
+static void flush_fifo(void);
void i2c_init (int speed, int slaveadd)
{
u16 scl;
+ outw(0x2, I2C_SYSC); /* for ES2 after soft reset */
+ udelay(1000);
+ outw(0x0, I2C_SYSC); /* will probably self clear but */
+
if (inw (I2C_CON) & I2C_CON_EN) {
outw (0, I2C_CON);
udelay (50000);
@@ -52,11 +56,14 @@ void i2c_init (int speed, int slaveadd)
/* own address */
outw (slaveadd, I2C_OA);
outw (I2C_CON_EN, I2C_CON);
- outw (0, I2C_CNT);
+
/* have to enable intrrupts or OMAP i2c module doesn't work */
outw (I2C_IE_XRDY_IE | I2C_IE_RRDY_IE | I2C_IE_ARDY_IE |
I2C_IE_NACK_IE | I2C_IE_AL_IE, I2C_IE);
udelay (1000);
+ flush_fifo();
+ outw (0xFFFF, I2C_STAT);
+ outw (0, I2C_CNT);
}
static int i2c_read_byte (u8 devaddr, u8 regoffset, u8 * value)
@@ -160,11 +167,15 @@ static int i2c_write_byte (u8 devaddr, u8 regoffset, u8 value)
}
if (!i2c_error) {
+ int eout = 200;
+
outw (I2C_CON_EN, I2C_CON);
while ((stat = inw (I2C_STAT)) || (inw (I2C_CON) & I2C_CON_MST)) {
udelay (1000);
/* have to read to clear intrrupt */
outw (0xFFFF, I2C_STAT);
+ if(--eout == 0) /* better leave with error than hang */
+ break;
}
}
flush_fifo();
@@ -173,7 +184,7 @@ static int i2c_write_byte (u8 devaddr, u8 regoffset, u8 value)
return i2c_error;
}
-void flush_fifo(void)
+static void flush_fifo(void)
{ u16 stat;
/* note: if you try and read data when its not there or ready
diff --git a/drivers/pc_keyb.c b/drivers/pc_keyb.c
index 07c7914..81d3e98 100644
--- a/drivers/pc_keyb.c
+++ b/drivers/pc_keyb.c
@@ -193,7 +193,7 @@ static char * kbd_initialize(void)
| KBD_MODE_DISABLE_MOUSE
| KBD_MODE_KCC);
- /* ibm powerpc portables need this to use scan-code set 1 -- Cort */
+ /* AMCC powerpc portables need this to use scan-code set 1 -- Cort */
kbd_write_command_w(KBD_CCMD_READ_MODE);
if (!(kbd_wait_for_input() & KBD_MODE_KCC)) {
/*
diff --git a/drivers/pci.c b/drivers/pci.c
index c618f5b..5360030 100644
--- a/drivers/pci.c
+++ b/drivers/pci.c
@@ -142,7 +142,7 @@ struct pci_controller *pci_bus_to_hose (int bus)
if (bus >= hose->first_busno && bus <= hose->last_busno)
return hose;
- debug ("pci_bus_to_hose() failed\n");
+ printf("pci_bus_to_hose() failed\n");
return NULL;
}
diff --git a/drivers/pci_auto.c b/drivers/pci_auto.c
index 3f26886..3302457 100644
--- a/drivers/pci_auto.c
+++ b/drivers/pci_auto.c
@@ -319,7 +319,18 @@ int pciauto_config_device(struct pci_controller *hose, pci_dev_t dev)
PCI_DEV(dev));
break;
#endif
-
+#ifdef CONFIG_MPC834X
+ case PCI_CLASS_BRIDGE_OTHER:
+ /*
+ * The host/PCI bridge 1 seems broken in 8349 - it presents
+ * itself as 'PCI_CLASS_BRIDGE_OTHER' and appears as an _agent_
+ * device claiming resources io/mem/irq.. we only allow for
+ * the PIMMR window to be allocated (BAR0 - 1MB size)
+ */
+ DEBUGF("PCI Autoconfig: Broken bridge found, only minimal config\n");
+ pciauto_setup_device(hose, dev, 0, hose->pci_mem, hose->pci_io);
+ break;
+#endif
default:
pciauto_setup_device(hose, dev, 6, hose->pci_mem, hose->pci_io);
break;
diff --git a/drivers/pci_indirect.c b/drivers/pci_indirect.c
index 5987ac4..e8f19f5 100644
--- a/drivers/pci_indirect.c
+++ b/drivers/pci_indirect.c
@@ -12,7 +12,7 @@
#include <common.h>
#ifdef CONFIG_PCI
-#ifndef __I386__
+#if (!defined(__I386__) && !defined(CONFIG_IXDP425))
#include <asm/processor.h>
#include <asm/io.h>
@@ -118,5 +118,5 @@ void pci_setup_indirect(struct pci_controller* hose, u32 cfg_addr, u32 cfg_data)
hose->cfg_data = (unsigned char *) cfg_data;
}
-#endif
-#endif
+#endif /* !__I386__ && !CONFIG_IXDP425 */
+#endif /* CONFIG_PCI */
diff --git a/drivers/pcnet.c b/drivers/pcnet.c
index 17e8044..da9ac7f 100644
--- a/drivers/pcnet.c
+++ b/drivers/pcnet.c
@@ -195,7 +195,7 @@ int pcnet_initialize(bd_t *bis)
/*
* Setup the PCI device.
*/
- pci_read_config_dword(devbusfn, PCI_BASE_ADDRESS_0, &dev->iobase);
+ pci_read_config_dword(devbusfn, PCI_BASE_ADDRESS_0, (unsigned int *)&dev->iobase);
dev->iobase &= ~0xf;
PCNET_DEBUG1("%s: devbusfn=0x%x iobase=0x%x: ",
diff --git a/drivers/smiLynxEM.c b/drivers/smiLynxEM.c
index 94092a3..20f9beb 100644
--- a/drivers/smiLynxEM.c
+++ b/drivers/smiLynxEM.c
@@ -129,7 +129,7 @@ static char SMI_SCR[] = {
};
static char SMI_EXT_CRT[] = {
0x31, 0x00, 0x32, 0x00, 0x33, 0x00, 0x34, 0x00, 0x35, 0x00,
- 0x36, 0x00, 0x3b, 0x00, 0x3c, 0x00, 0x3d, 0x00, 0x3e, 0x00, 0x3f, 0x00
+ 0x36, 0x00, 0x3b, 0x00, 0x3c, 0x00, 0x3d, 0x00, 0x3e, 0x00, 0x3f, 0x00,
};
static char SMI_ATTR [] = {
0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03, 0x04, 0x04, 0x05, 0x05,
@@ -139,21 +139,24 @@ static char SMI_ATTR [] = {
};
static char SMI_GCR[18] = {
0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x40,
- 0x06, 0x05, 0x07, 0x0f, 0x08, 0xff
+ 0x06, 0x05, 0x07, 0x0f, 0x08, 0xff,
};
static char SMI_SEQR[] = {
- 0x00, 0x00, 0x01, 0x01, 0x02, 0x0f, 0x03, 0x03, 0x04, 0x0e, 0x00, 0x03
+ 0x00, 0x00, 0x01, 0x01, 0x02, 0x0f, 0x03, 0x03, 0x04, 0x0e, 0x00, 0x03,
};
static char SMI_PCR [] = {
- 0x20, 0x04, 0x21, 0x30, 0x22, 0x00, 0x23, 0x00, 0x24, 0x00
+ 0x20, 0x04, 0x21, 0x30, 0x22, 0x00, 0x23, 0x00, 0x24, 0x00,
};
static char SMI_MCR[] = {
0x60, 0x01, 0x61, 0x00,
+#ifdef CONFIG_HMI1001
+ 0x62, 0x74, /* Memory type is not configured by pins on HMI1001 */
+#endif
};
static char SMI_HCR[] = {
0x80, 0xff, 0x81, 0x07, 0x82, 0x00, 0x83, 0xff, 0x84, 0xff, 0x88, 0x00,
- 0x89, 0x02, 0x8a, 0x80, 0x8b, 0x01, 0x8c, 0xff, 0x8d, 0x00
+ 0x89, 0x02, 0x8a, 0x80, 0x8b, 0x01, 0x8c, 0xff, 0x8d, 0x00,
};
@@ -522,7 +525,8 @@ static unsigned int FindPQ (unsigned int freq, unsigned int *pp, unsigned int *p
/*****************************************************************************/
static void smiLoadCcr (struct ctfb_res_modes *var, unsigned short device_id)
{
- unsigned int p, q;
+ unsigned int p = 0;
+ unsigned int q = 0;
long long freq;
register GraphicDevice *pGD = (GraphicDevice *)&smi;
diff --git a/drivers/tsec.c b/drivers/tsec.c
index 0c8b0de..f860dae 100644
--- a/drivers/tsec.c
+++ b/drivers/tsec.c
@@ -21,8 +21,9 @@
#if defined(CONFIG_TSEC_ENET)
#include "tsec.h"
+#include "miiphy.h"
-#define TX_BUF_CNT 2
+#define TX_BUF_CNT 2
static uint rxIdx; /* index of the current RX buffer */
static uint txIdx; /* index of the current TX buffer */
@@ -120,6 +121,10 @@ struct phy_info * get_phy_info(struct eth_device *dev);
void phy_run_commands(struct tsec_private *priv, struct phy_cmd *cmd);
static void adjust_link(struct eth_device *dev);
static void relocate_cmds(void);
+static int tsec_miiphy_write(char *devname, unsigned char addr,
+ unsigned char reg, unsigned short value);
+static int tsec_miiphy_read(char *devname, unsigned char addr,
+ unsigned char reg, unsigned short *value);
/* Initialize device structure. Returns success if PHY
* initialization succeeded (i.e. if it recognizes the PHY)
@@ -169,6 +174,11 @@ int tsec_initialize(bd_t *bis, int index, char *devname)
priv->regs->maccfg1 |= MACCFG1_SOFT_RESET;
priv->regs->maccfg1 &= ~(MACCFG1_SOFT_RESET);
+#if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII) \
+ && !defined(BITBANGMII)
+ miiphy_register(dev->name, tsec_miiphy_read, tsec_miiphy_write);
+#endif
+
/* Try to initialize PHY here, and return */
return init_phy(dev);
}
@@ -200,11 +210,11 @@ int tsec_init(struct eth_device* dev, bd_t * bd)
for(i=0;i<MAC_ADDR_LEN;i++) {
tmpbuf[MAC_ADDR_LEN - 1 - i] = dev->enetaddr[i];
}
- (uint)(regs->macstnaddr1) = *((uint *)(tmpbuf));
+ regs->macstnaddr1 = *((uint *)(tmpbuf));
tempval = *((uint *)(tmpbuf +4));
- (uint)(regs->macstnaddr2) = tempval;
+ regs->macstnaddr2 = tempval;
/* reset the indices to zero */
rxIdx = 0;
@@ -338,16 +348,35 @@ uint mii_cr_init(uint mii_reg, struct tsec_private *priv)
* auto-negotiation */
uint mii_parse_sr(uint mii_reg, struct tsec_private *priv)
{
- uint timeout = TSEC_TIMEOUT;
-
- if(mii_reg & MIIM_STATUS_LINK)
- priv->link = 1;
- else
- priv->link = 0;
+ /*
+ * Wait if PHY is capable of autonegotiation and autonegotiation is not complete
+ */
+ mii_reg = read_phy_reg(priv, MIIM_STATUS);
+ if ((mii_reg & PHY_BMSR_AUTN_ABLE) && !(mii_reg & PHY_BMSR_AUTN_COMP)) {
+ int i = 0;
+
+ puts ("Waiting for PHY auto negotiation to complete");
+ while (!((mii_reg & PHY_BMSR_AUTN_COMP) && (mii_reg & MIIM_STATUS_LINK))) {
+ /*
+ * Timeout reached ?
+ */
+ if (i > PHY_AUTONEGOTIATE_TIMEOUT) {
+ puts (" TIMEOUT !\n");
+ priv->link = 0;
+ break;
+ }
- if(priv->link) {
- while((!(mii_reg & MIIM_STATUS_AN_DONE)) && timeout--)
+ if ((i++ % 1000) == 0) {
+ putc ('.');
+ }
+ udelay (1000); /* 1 ms */
mii_reg = read_phy_reg(priv, MIIM_STATUS);
+ }
+ puts (" done\n");
+ priv->link = 1;
+ udelay (500000); /* another 500 ms (results in faster booting) */
+ } else {
+ priv->link = 1;
}
return 0;
@@ -360,6 +389,34 @@ uint mii_parse_88E1011_psr(uint mii_reg, struct tsec_private *priv)
{
uint speed;
+ mii_reg = read_phy_reg(priv, MIIM_88E1011_PHY_STATUS);
+
+ if (!((mii_reg & MIIM_88E1011_PHYSTAT_SPDDONE) &&
+ (mii_reg & MIIM_88E1011_PHYSTAT_LINK))) {
+ int i = 0;
+
+ puts ("Waiting for PHY realtime link");
+ while (!((mii_reg & MIIM_88E1011_PHYSTAT_SPDDONE) &&
+ (mii_reg & MIIM_88E1011_PHYSTAT_LINK))) {
+ /*
+ * Timeout reached ?
+ */
+ if (i > PHY_AUTONEGOTIATE_TIMEOUT) {
+ puts (" TIMEOUT !\n");
+ priv->link = 0;
+ break;
+ }
+
+ if ((i++ % 1000) == 0) {
+ putc ('.');
+ }
+ udelay (1000); /* 1 ms */
+ mii_reg = read_phy_reg(priv, MIIM_88E1011_PHY_STATUS);
+ }
+ puts (" done\n");
+ udelay (500000); /* another 500 ms (results in faster booting) */
+ }
+
if(mii_reg & MIIM_88E1011_PHYSTAT_DUPLEX)
priv->duplexity = 1;
else
@@ -926,8 +983,7 @@ struct phy_info * get_phy_info(struct eth_device *dev)
printf("%s: PHY id %x is not supported!\n", dev->name, phy_ID);
return NULL;
} else {
- printf("%s: PHY is %s (%x)\n", dev->name, theInfo->name,
- phy_ID);
+ debug("%s: PHY is %s (%x)\n", dev->name, theInfo->name, phy_ID);
}
return theInfo;
@@ -1012,7 +1068,8 @@ static void relocate_cmds(void)
}
-#ifndef CONFIG_BITBANGMII
+#if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII) \
+ && !defined(BITBANGMII)
struct tsec_private * get_priv_for_phy(unsigned char phyaddr)
{
@@ -1032,7 +1089,8 @@ struct tsec_private * get_priv_for_phy(unsigned char phyaddr)
* Returns:
* 0 on success
*/
-int miiphy_read(unsigned char addr, unsigned char reg, unsigned short *value)
+static int tsec_miiphy_read(char *devname, unsigned char addr,
+ unsigned char reg, unsigned short *value)
{
unsigned short ret;
struct tsec_private *priv = get_priv_for_phy(addr);
@@ -1054,7 +1112,8 @@ int miiphy_read(unsigned char addr, unsigned char reg, unsigned short *value)
* Returns:
* 0 on success
*/
-int miiphy_write(unsigned char addr, unsigned char reg, unsigned short value)
+static int tsec_miiphy_write(char *devname, unsigned char addr,
+ unsigned char reg, unsigned short value)
{
struct tsec_private *priv = get_priv_for_phy(addr);
@@ -1068,6 +1127,7 @@ int miiphy_write(unsigned char addr, unsigned char reg, unsigned short value)
return 0;
}
-#endif /* CONFIG_BITBANGMII */
+#endif /* defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)
+ && !defined(BITBANGMII) */
#endif /* CONFIG_TSEC_ENET */
diff --git a/drivers/tsec.h b/drivers/tsec.h
index 15961d7..c26fcc0 100644
--- a/drivers/tsec.h
+++ b/drivers/tsec.h
@@ -40,6 +40,8 @@
#define TSEC_TIMEOUT 1000
#define TOUT_LOOP 1000000
+#define PHY_AUTONEGOTIATE_TIMEOUT 5000 /* in ms */
+
/* MAC register bits */
#define MACCFG1_SOFT_RESET 0x80000000
#define MACCFG1_RESET_RX_MC 0x00080000
@@ -77,6 +79,7 @@
#define MIIM_CONTROL 0x00
#define MIIM_CONTROL_RESET 0x00009140
#define MIIM_CONTROL_INIT 0x00001140
+#define MIIM_CONTROL_RESTART 0x00001340
#define MIIM_ANEN 0x00001000
#define MIIM_CR 0x00
@@ -86,6 +89,8 @@
#define MIIM_STATUS 0x1
#define MIIM_STATUS_AN_DONE 0x00000020
#define MIIM_STATUS_LINK 0x0004
+#define PHY_BMSR_AUTN_ABLE 0x0008
+#define PHY_BMSR_AUTN_COMP 0x0020
#define MIIM_PHYIR1 0x2
#define MIIM_PHYIR2 0x3