summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorNobuhiro Iwamatsu <iwamatsu@nigauri.org>2007-11-29 00:56:37 +0900
committerNobuhiro Iwamatsu <iwamatsu@nigauri.org>2007-11-29 00:56:37 +0900
commit7fc792895be3c0edf423c4038992b40345672a12 (patch)
tree6247dce2d1e72aa17fd2d7a138af66158d02f319 /drivers
parenteda3e1e6619ad0bee94ae4b16c99d88e77e2af13 (diff)
parentf92edbd8a0ef16a2b9127cbb564c09685728e4b0 (diff)
downloadtalos-obmc-uboot-7fc792895be3c0edf423c4038992b40345672a12.tar.gz
talos-obmc-uboot-7fc792895be3c0edf423c4038992b40345672a12.zip
Merge git://www.denx.de/git/u-boot
Conflicts: drivers/Makefile
Diffstat (limited to 'drivers')
-rwxr-xr-xdrivers/Makefile146
-rw-r--r--[-rwxr-xr-x]drivers/at45.c316
-rw-r--r--drivers/ati_radeon_fb.c8
-rw-r--r--drivers/bios_emulator/besys.c2
-rw-r--r--drivers/bios_emulator/biosemu.c6
-rw-r--r--drivers/ds1722.c4
-rw-r--r--drivers/fsl_pci_init.c8
-rw-r--r--drivers/isp116x-hcd.c112
-rw-r--r--drivers/mw_eeprom.c4
-rw-r--r--drivers/nand/Makefile10
-rw-r--r--drivers/ne2000.c57
-rw-r--r--drivers/ne2000.h2
-rw-r--r--drivers/onenand/Makefile44
-rw-r--r--drivers/onenand/onenand_base.c1294
-rw-r--r--drivers/onenand/onenand_bbt.c265
-rw-r--r--drivers/s3c4510b_eth.c2
-rw-r--r--drivers/serial/Makefile2
-rw-r--r--drivers/serial/serial_pl010.c (renamed from drivers/serial_pl010.c)0
-rw-r--r--drivers/serial/serial_pl011.c (renamed from drivers/serial_pl011.c)0
-rw-r--r--drivers/serial/serial_pl011.h (renamed from drivers/serial_pl011.h)0
-rw-r--r--drivers/serial_xuartlite.c2
-rw-r--r--drivers/sk98lin/Makefile26
-rw-r--r--drivers/tsec.c4
-rw-r--r--drivers/tsi108_i2c.c2
-rw-r--r--drivers/tsi108_pci.c3
-rw-r--r--drivers/uli526x.c996
-rw-r--r--drivers/usb_ohci.c5
27 files changed, 3027 insertions, 293 deletions
diff --git a/drivers/Makefile b/drivers/Makefile
index fe32a74098..480b3581f6 100755
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -1,5 +1,5 @@
#
-# (C) Copyright 2000-2006
+# (C) Copyright 2000-2007
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
#
# See file CREDITS for list of people who contributed to this
@@ -27,35 +27,123 @@ include $(TOPDIR)/config.mk
LIB = $(obj)libdrivers.a
-COBJS = 3c589.o 5701rls.o ali512x.o at45.o ata_piix.o atmel_usart.o \
- bcm570x.o bcm570x_autoneg.o cfb_console.o cfi_flash.o \
- cs8900.o ct69000.o dataflash.o dc2114x.o dm9000x.o \
- e1000.o eepro100.o enc28j60.o \
- i8042.o inca-ip_sw.o isp116x-hcd.o keyboard.o \
- lan91c96.o macb.o \
- natsemi.o ne2000.o netarm_eth.o netconsole.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 \
- rtl8019.o rtl8139.o rtl8169.o \
- s3c4510b_eth.o s3c4510b_uart.o \
- sed13806.o sed156x.o \
- serial.o serial_max3100.o serial_sh.o \
- serial_pl010.o serial_pl011.o serial_xuartlite.o \
- sil680.o sl811_usb.o sm501.o smc91111.o smiLynxEM.o \
- status_led.o sym53c8xx.o systemace.o ahci.o \
- ti_pci1410a.o tigon3.o tsec.o \
- tsi108_eth.o tsi108_i2c.o tsi108_pci.o \
- usb_ohci.o \
- usbdcore.o usbdcore_ep0.o usbdcore_mpc8xx.o usbdcore_omap1510.o \
- usbtty.o \
- videomodes.o w83c553f.o \
- ks8695eth.o \
- pxa_pcmcia.o mpc8xx_pcmcia.o tqm8xx_pcmcia.o \
- rpx_pcmcia.o \
- fsl_i2c.o fsl_pci_init.o ati_radeon_fb.o
+COBJS-y += ali512x.o
+COBJS-y += ds1722.o
+COBJS-y += ns87308.o
+COBJS-y += status_led.o
+#
+# Block and Flash Drivers
+#
+COBJS-y += ahci.o
+COBJS-y += at45.o
+COBJS-y += ata_piix.o
+COBJS-y += cfi_flash.o
+COBJS-y += dataflash.o
+COBJS-y += mw_eeprom.o
+COBJS-y += sil680.o
+COBJS-y += sym53c8xx.o
+COBJS-y += systemace.o
+
+#
+# Console Drivers
+#
+COBJS-y += ati_radeon_fb.o
+COBJS-y += atmel_usart.o
+COBJS-y += cfb_console.o
+COBJS-y += ct69000.o
+COBJS-y += i8042.o
+COBJS-y += keyboard.o
+COBJS-y += netconsole.o
+COBJS-y += ns16550.o
+COBJS-y += pc_keyb.o
+COBJS-y += ps2ser.o
+COBJS-y += ps2mult.o
+COBJS-y += s3c4510b_uart.o
+COBJS-y += sed13806.o
+COBJS-y += sed156x.o
+COBJS-y += serial.o
+COBJS-y += serial_max3100.o
+COBJS-y += serial_xuartlite.o
+COBJS-y += sm501.o
+COBJS-y += smiLynxEM.o
+COBJS-y += usbtty.o
+COBJS-y += videomodes.o
+
+#
+# I2C Drivers
+#
+COBJS-y += omap1510_i2c.o
+COBJS-y += omap24xx_i2c.o
+COBJS-y += tsi108_i2c.o
+COBJS-y += fsl_i2c.o
+
+#
+# Network Drivers
+#
+COBJS-y += 3c589.o
+COBJS-y += bcm570x.o bcm570x_autoneg.o 5701rls.o
+COBJS-y += cs8900.o
+COBJS-y += dc2114x.o
+COBJS-y += dm9000x.o
+COBJS-y += e1000.o
+COBJS-y += eepro100.o
+COBJS-y += enc28j60.o
+COBJS-y += inca-ip_sw.o
+COBJS-y += ks8695eth.o
+COBJS-y += lan91c96.o
+COBJS-y += macb.o
+COBJS-y += natsemi.o
+COBJS-y += ne2000.o
+COBJS-y += netarm_eth.o
+COBJS-y += ns7520_eth.o
+COBJS-y += ns8382x.o
+COBJS-y += pcnet.o
+COBJS-y += plb2800_eth.o
+COBJS-y += rtl8019.o
+COBJS-y += rtl8139.o
+COBJS-y += rtl8169.o
+COBJS-y += s3c4510b_eth.o
+COBJS-y += smc91111.o
+COBJS-y += tigon3.o
+COBJS-y += tsec.o
+COBJS-y += tsi108_eth.o
+COBJS-y += uli526x.o
+
+#
+# PCI/PCMCIA device drivers
+#
+COBJS-y += fsl_pci_init.o
+COBJS-y += mpc8xx_pcmcia.o
+COBJS-y += pci.o
+COBJS-y += pci_auto.o
+COBJS-y += pci_indirect.o
+COBJS-y += pxa_pcmcia.o
+COBJS-y += rpx_pcmcia.o
+COBJS-y += ti_pci1410a.o
+COBJS-y += tqm8xx_pcmcia.o
+COBJS-y += tsi108_pci.o
+COBJS-y += w83c553f.o
+
+#
+# USB Drivers
+#
+COBJS-y += isp116x-hcd.o
+COBJS-y += sl811_usb.o
+COBJS-y += usb_ohci.o
+COBJS-y += usbdcore.o
+COBJS-y += usbdcore_ep0.o
+COBJS-y += usbdcore_mpc8xx.o
+COBJS-y += usbdcore_omap1510.o
+
+#
+# Miscellaneous Drivers
+#
+COBJS-y += ali512x.o
+COBJS-y += ns87308.o
+COBJS-y += status_led.o
+
+COBJS := $(COBJS-y)
SRCS := $(COBJS:.o=.c)
OBJS := $(addprefix $(obj),$(COBJS))
diff --git a/drivers/at45.c b/drivers/at45.c
index 507ff36d47..dac987a43a 100755..100644
--- a/drivers/at45.c
+++ b/drivers/at45.c
@@ -27,33 +27,31 @@
/*
* spi.c API
*/
-extern unsigned int AT91F_SpiWrite (AT91PS_DataflashDesc pDesc);
-extern void AT91F_SpiEnable(int cs);
+extern unsigned int AT91F_SpiWrite(AT91PS_DataflashDesc pDesc);
+extern void AT91F_SpiEnable(int cs);
#define AT91C_TIMEOUT_WRDY 200000
-
/*----------------------------------------------------------------------*/
/* \fn AT91F_DataFlashSendCommand */
/* \brief Generic function to send a command to the dataflash */
/*----------------------------------------------------------------------*/
-AT91S_DataFlashStatus AT91F_DataFlashSendCommand(
- AT91PS_DataFlash pDataFlash,
- unsigned char OpCode,
- unsigned int CmdSize,
- unsigned int DataflashAddress)
+AT91S_DataFlashStatus AT91F_DataFlashSendCommand(AT91PS_DataFlash pDataFlash,
+ unsigned char OpCode,
+ unsigned int CmdSize,
+ unsigned int DataflashAddress)
{
unsigned int adr;
- if ( (pDataFlash->pDataFlashDesc->state) != IDLE)
+ if ((pDataFlash->pDataFlashDesc->state) != IDLE)
return DATAFLASH_BUSY;
/* process the address to obtain page address and byte address */
adr = ((DataflashAddress / (pDataFlash->pDevice->pages_size)) <<
- pDataFlash->pDevice->page_offset) + (DataflashAddress %
- (pDataFlash->pDevice->pages_size));
+ pDataFlash->pDevice->page_offset) +
+ (DataflashAddress % (pDataFlash->pDevice->pages_size));
- /* fill the command buffer */
+ /* fill the command buffer */
pDataFlash->pDataFlashDesc->command[0] = OpCode;
if (pDataFlash->pDevice->pages_number >= 16384) {
pDataFlash->pDataFlashDesc->command[1] =
@@ -78,16 +76,16 @@ AT91S_DataFlashStatus AT91F_DataFlashSendCommand(
pDataFlash->pDataFlashDesc->command[7] = 0;
/* Initialize the SpiData structure for the spi write fuction */
- pDataFlash->pDataFlashDesc->tx_cmd_pt =
+ pDataFlash->pDataFlashDesc->tx_cmd_pt =
pDataFlash->pDataFlashDesc->command;
- pDataFlash->pDataFlashDesc->tx_cmd_size = CmdSize;
- pDataFlash->pDataFlashDesc->rx_cmd_pt =
+ pDataFlash->pDataFlashDesc->tx_cmd_size = CmdSize;
+ pDataFlash->pDataFlashDesc->rx_cmd_pt =
pDataFlash->pDataFlashDesc->command;
- pDataFlash->pDataFlashDesc->rx_cmd_size = CmdSize;
+ pDataFlash->pDataFlashDesc->rx_cmd_size = CmdSize;
/* send the command and read the data */
- return AT91F_SpiWrite (pDataFlash->pDataFlashDesc); }
-
+ return AT91F_SpiWrite(pDataFlash->pDataFlashDesc);
+}
/*----------------------------------------------------------------------*/
/* \fn AT91F_DataFlashGetStatus */
@@ -98,50 +96,49 @@ AT91S_DataFlashStatus AT91F_DataFlashGetStatus(AT91PS_DataflashDesc pDesc)
AT91S_DataFlashStatus status;
/* if a transfert is in progress ==> return 0 */
- if( (pDesc->state) != IDLE)
+ if ((pDesc->state) != IDLE)
return DATAFLASH_BUSY;
/* first send the read status command (D7H) */
pDesc->command[0] = DB_STATUS;
pDesc->command[1] = 0;
- pDesc->DataFlash_state = GET_STATUS;
- pDesc->tx_data_size = 0; /* Transmit the command */
- /* and receive response */
- pDesc->tx_cmd_pt = pDesc->command;
- pDesc->rx_cmd_pt = pDesc->command;
- pDesc->rx_cmd_size = 2;
- pDesc->tx_cmd_size = 2;
- status = AT91F_SpiWrite (pDesc);
+ pDesc->DataFlash_state = GET_STATUS;
+ pDesc->tx_data_size = 0; /* Transmit the command */
+ /* and receive response */
+ pDesc->tx_cmd_pt = pDesc->command;
+ pDesc->rx_cmd_pt = pDesc->command;
+ pDesc->rx_cmd_size = 2;
+ pDesc->tx_cmd_size = 2;
+ status = AT91F_SpiWrite(pDesc);
- pDesc->DataFlash_state = *( (unsigned char *) (pDesc->rx_cmd_pt) +1);
+ pDesc->DataFlash_state = *((unsigned char *)(pDesc->rx_cmd_pt) + 1);
return status;
}
-
/*----------------------------------------------------------------------*/
/* \fn AT91F_DataFlashWaitReady */
/* \brief wait for dataflash ready (bit7 of the status register == 1) */
/*----------------------------------------------------------------------*/
AT91S_DataFlashStatus AT91F_DataFlashWaitReady(AT91PS_DataflashDesc
-pDataFlashDesc, unsigned int timeout)
+ pDataFlashDesc,
+ unsigned int timeout)
{
pDataFlashDesc->DataFlash_state = IDLE;
do {
AT91F_DataFlashGetStatus(pDataFlashDesc);
timeout--;
- } while( ((pDataFlashDesc->DataFlash_state & 0x80) != 0x80) &&
- (timeout > 0) );
+ } while (((pDataFlashDesc->DataFlash_state & 0x80) != 0x80) &&
+ (timeout > 0));
- if((pDataFlashDesc->DataFlash_state & 0x80) != 0x80)
+ if ((pDataFlashDesc->DataFlash_state & 0x80) != 0x80)
return DATAFLASH_ERROR;
return DATAFLASH_OK;
}
-
/*--------------------------------------------------------------------------*/
/* Function Name : AT91F_DataFlashContinuousRead */
/* Object : Continuous stream Read */
@@ -151,17 +148,17 @@ pDataFlashDesc, unsigned int timeout)
/* : <sizeToRead> = data buffer size */
/* Return value : State of the dataflash */
/*--------------------------------------------------------------------------*/
-AT91S_DataFlashStatus AT91F_DataFlashContinuousRead (
- AT91PS_DataFlash pDataFlash,
- int src,
- unsigned char *dataBuffer,
- int sizeToRead )
+AT91S_DataFlashStatus AT91F_DataFlashContinuousRead(
+ AT91PS_DataFlash pDataFlash,
+ int src,
+ unsigned char *dataBuffer,
+ int sizeToRead)
{
AT91S_DataFlashStatus status;
/* Test the size to read in the device */
- if ( (src + sizeToRead) >
- (pDataFlash->pDevice->pages_size *
- (pDataFlash->pDevice->pages_number)))
+ if ((src + sizeToRead) >
+ (pDataFlash->pDevice->pages_size *
+ (pDataFlash->pDevice->pages_number)))
return DATAFLASH_MEMORY_OVERFLOW;
pDataFlash->pDataFlashDesc->rx_data_pt = dataBuffer;
@@ -169,13 +166,12 @@ AT91S_DataFlashStatus AT91F_DataFlashContinuousRead (
pDataFlash->pDataFlashDesc->tx_data_pt = dataBuffer;
pDataFlash->pDataFlashDesc->tx_data_size = sizeToRead;
- status = AT91F_DataFlashSendCommand
- (pDataFlash, DB_CONTINUOUS_ARRAY_READ, 8, src);
+ status = AT91F_DataFlashSendCommand(
+ pDataFlash, DB_CONTINUOUS_ARRAY_READ, 8, src);
/* Send the command to the dataflash */
- return(status);
+ return (status);
}
-
/*---------------------------------------------------------------------------*/
/* Function Name : AT91F_DataFlashPagePgmBuf */
/* Object : Main memory page program thru buffer 1 or buffer 2 */
@@ -185,11 +181,10 @@ AT91S_DataFlashStatus AT91F_DataFlashContinuousRead (
/* : <SizeToWrite> = data buffer size */
/* Return value : State of the dataflash */
/*---------------------------------------------------------------------------*/
-AT91S_DataFlashStatus AT91F_DataFlashPagePgmBuf(
- AT91PS_DataFlash pDataFlash,
- unsigned char *src,
- unsigned int dest,
- unsigned int SizeToWrite)
+AT91S_DataFlashStatus AT91F_DataFlashPagePgmBuf(AT91PS_DataFlash pDataFlash,
+ unsigned char *src,
+ unsigned int dest,
+ unsigned int SizeToWrite)
{
int cmdsize;
pDataFlash->pDataFlashDesc->tx_data_pt = src;
@@ -201,9 +196,9 @@ AT91S_DataFlashStatus AT91F_DataFlashPagePgmBuf(
/* Send the command to the dataflash */
if (pDataFlash->pDevice->pages_number >= 16384)
cmdsize = 5;
- return(AT91F_DataFlashSendCommand (pDataFlash, DB_PAGE_PGM_BUF1,
-cmdsize, dest)); }
-
+ return (AT91F_DataFlashSendCommand(
+ pDataFlash, DB_PAGE_PGM_BUF1, cmdsize, dest));
+}
/*---------------------------------------------------------------------------*/
/* Function Name : AT91F_MainMemoryToBufferTransfert */
@@ -214,26 +209,29 @@ cmdsize, dest)); }
/* Return value : State of the dataflash */
/*---------------------------------------------------------------------------*/
AT91S_DataFlashStatus AT91F_MainMemoryToBufferTransfert(
- AT91PS_DataFlash pDataFlash,
- unsigned char BufferCommand,
- unsigned int page)
+ AT91PS_DataFlash
+ pDataFlash,
+ unsigned char
+ BufferCommand,
+ unsigned int page)
{
int cmdsize;
/* Test if the buffer command is legal */
- if ((BufferCommand != DB_PAGE_2_BUF1_TRF)
- && (BufferCommand != DB_PAGE_2_BUF2_TRF))
+ if ((BufferCommand != DB_PAGE_2_BUF1_TRF) &&
+ (BufferCommand != DB_PAGE_2_BUF2_TRF)) {
return DATAFLASH_BAD_COMMAND;
+ }
/* no data to transmit or receive */
pDataFlash->pDataFlashDesc->tx_data_size = 0;
cmdsize = 4;
if (pDataFlash->pDevice->pages_number >= 16384)
cmdsize = 5;
- return(AT91F_DataFlashSendCommand (pDataFlash, BufferCommand, cmdsize,
-page*pDataFlash->pDevice->pages_size));
+ return (AT91F_DataFlashSendCommand(
+ pDataFlash, BufferCommand, cmdsize,
+ page * pDataFlash->pDevice->pages_size));
}
-
/*-------------------------------------------------------------------------- */
/* Function Name : AT91F_DataFlashWriteBuffer */
/* Object : Write data to the internal sram buffer 1 or 2 */
@@ -244,58 +242,61 @@ page*pDataFlash->pDevice->pages_size));
/* : <SizeToWrite> = data buffer size */
/* Return value : State of the dataflash */
/*---------------------------------------------------------------------------*/
-AT91S_DataFlashStatus AT91F_DataFlashWriteBuffer (
- AT91PS_DataFlash pDataFlash,
- unsigned char BufferCommand,
- unsigned char *dataBuffer,
- unsigned int bufferAddress,
- int SizeToWrite )
+AT91S_DataFlashStatus AT91F_DataFlashWriteBuffer(
+ AT91PS_DataFlash pDataFlash,
+ unsigned char BufferCommand,
+ unsigned char *dataBuffer,
+ unsigned int bufferAddress,
+ int SizeToWrite)
{
int cmdsize;
/* Test if the buffer command is legal */
- if ((BufferCommand != DB_BUF1_WRITE)
- && (BufferCommand != DB_BUF2_WRITE))
+ if ((BufferCommand != DB_BUF1_WRITE) &&
+ (BufferCommand != DB_BUF2_WRITE)) {
return DATAFLASH_BAD_COMMAND;
+ }
/* buffer address must be lower than page size */
if (bufferAddress > pDataFlash->pDevice->pages_size)
return DATAFLASH_BAD_ADDRESS;
- if ( (pDataFlash->pDataFlashDesc->state) != IDLE)
+ if ((pDataFlash->pDataFlashDesc->state) != IDLE)
return DATAFLASH_BUSY;
/* Send first Write Command */
pDataFlash->pDataFlashDesc->command[0] = BufferCommand;
pDataFlash->pDataFlashDesc->command[1] = 0;
if (pDataFlash->pDevice->pages_number >= 16384) {
- pDataFlash->pDataFlashDesc->command[2] = 0;
- pDataFlash->pDataFlashDesc->command[3] =
+ pDataFlash->pDataFlashDesc->command[2] = 0;
+ pDataFlash->pDataFlashDesc->command[3] =
(unsigned char)(((unsigned int)(bufferAddress &
- pDataFlash->pDevice->byte_mask)) >> 8);
- pDataFlash->pDataFlashDesc->command[4] =
- (unsigned char)((unsigned int)bufferAddress & 0x00FF);
+ pDataFlash->pDevice->
+ byte_mask)) >> 8);
+ pDataFlash->pDataFlashDesc->command[4] =
+ (unsigned char)((unsigned int)bufferAddress & 0x00FF);
cmdsize = 5;
} else {
- pDataFlash->pDataFlashDesc->command[2] =
+ pDataFlash->pDataFlashDesc->command[2] =
(unsigned char)(((unsigned int)(bufferAddress &
- pDataFlash->pDevice->byte_mask)) >> 8);
- pDataFlash->pDataFlashDesc->command[3] =
- (unsigned char)((unsigned int)bufferAddress & 0x00FF);
- pDataFlash->pDataFlashDesc->command[4] = 0;
+ pDataFlash->pDevice->
+ byte_mask)) >> 8);
+ pDataFlash->pDataFlashDesc->command[3] =
+ (unsigned char)((unsigned int)bufferAddress & 0x00FF);
+ pDataFlash->pDataFlashDesc->command[4] = 0;
cmdsize = 4;
}
- pDataFlash->pDataFlashDesc->tx_cmd_pt =
+ pDataFlash->pDataFlashDesc->tx_cmd_pt =
pDataFlash->pDataFlashDesc->command;
pDataFlash->pDataFlashDesc->tx_cmd_size = cmdsize;
- pDataFlash->pDataFlashDesc->rx_cmd_pt =
+ pDataFlash->pDataFlashDesc->rx_cmd_pt =
pDataFlash->pDataFlashDesc->command;
pDataFlash->pDataFlashDesc->rx_cmd_size = cmdsize;
- pDataFlash->pDataFlashDesc->rx_data_pt = dataBuffer;
- pDataFlash->pDataFlashDesc->tx_data_pt = dataBuffer;
- pDataFlash->pDataFlashDesc->rx_data_size = SizeToWrite;
- pDataFlash->pDataFlashDesc->tx_data_size = SizeToWrite;
+ pDataFlash->pDataFlashDesc->rx_data_pt = dataBuffer;
+ pDataFlash->pDataFlashDesc->tx_data_pt = dataBuffer;
+ pDataFlash->pDataFlashDesc->rx_data_size = SizeToWrite;
+ pDataFlash->pDataFlashDesc->tx_data_size = SizeToWrite;
return AT91F_SpiWrite(pDataFlash->pDataFlashDesc);
}
@@ -309,22 +310,22 @@ AT91S_DataFlashStatus AT91F_DataFlashWriteBuffer (
/* Return value : State of the dataflash */
/*---------------------------------------------------------------------------*/
AT91S_DataFlashStatus AT91F_PageErase(
- AT91PS_DataFlash pDataFlash,
- unsigned int page)
+ AT91PS_DataFlash pDataFlash,
+ unsigned int page)
{
int cmdsize;
/* Test if the buffer command is legal */
/* no data to transmit or receive */
- pDataFlash->pDataFlashDesc->tx_data_size = 0;
+ pDataFlash->pDataFlashDesc->tx_data_size = 0;
cmdsize = 4;
if (pDataFlash->pDevice->pages_number >= 16384)
cmdsize = 5;
- return(AT91F_DataFlashSendCommand (pDataFlash, DB_PAGE_ERASE, cmdsize,
-page*pDataFlash->pDevice->pages_size));
+ return (AT91F_DataFlashSendCommand(pDataFlash,
+ DB_PAGE_ERASE, cmdsize,
+ page * pDataFlash->pDevice->pages_size));
}
-
/*---------------------------------------------------------------------------*/
/* Function Name : AT91F_BlockErase */
/* Object : Erase a Block */
@@ -334,18 +335,19 @@ page*pDataFlash->pDevice->pages_size));
/* Return value : State of the dataflash */
/*---------------------------------------------------------------------------*/
AT91S_DataFlashStatus AT91F_BlockErase(
- AT91PS_DataFlash pDataFlash,
- unsigned int block)
+ AT91PS_DataFlash pDataFlash,
+ unsigned int block)
{
int cmdsize;
/* Test if the buffer command is legal */
/* no data to transmit or receive */
- pDataFlash->pDataFlashDesc->tx_data_size = 0;
+ pDataFlash->pDataFlashDesc->tx_data_size = 0;
cmdsize = 4;
if (pDataFlash->pDevice->pages_number >= 16384)
cmdsize = 5;
- return(AT91F_DataFlashSendCommand (pDataFlash, DB_BLOCK_ERASE,cmdsize,
-block*8*pDataFlash->pDevice->pages_size));
+ return (AT91F_DataFlashSendCommand(pDataFlash, DB_BLOCK_ERASE, cmdsize,
+ block * 8 *
+ pDataFlash->pDevice->pages_size));
}
/*---------------------------------------------------------------------------*/
@@ -356,17 +358,16 @@ block*8*pDataFlash->pDevice->pages_size));
/* : <dest> = main memory address */
/* Return value : State of the dataflash */
/*---------------------------------------------------------------------------*/
-AT91S_DataFlashStatus AT91F_WriteBufferToMain (
- AT91PS_DataFlash pDataFlash,
- unsigned char BufferCommand,
- unsigned int dest )
+AT91S_DataFlashStatus AT91F_WriteBufferToMain(AT91PS_DataFlash pDataFlash,
+ unsigned char BufferCommand,
+ unsigned int dest)
{
int cmdsize;
/* Test if the buffer command is correct */
if ((BufferCommand != DB_BUF1_PAGE_PGM) &&
- (BufferCommand != DB_BUF1_PAGE_ERASE_PGM) &&
- (BufferCommand != DB_BUF2_PAGE_PGM) &&
- (BufferCommand != DB_BUF2_PAGE_ERASE_PGM) )
+ (BufferCommand != DB_BUF1_PAGE_ERASE_PGM) &&
+ (BufferCommand != DB_BUF2_PAGE_PGM) &&
+ (BufferCommand != DB_BUF2_PAGE_ERASE_PGM))
return DATAFLASH_BAD_COMMAND;
/* no data to transmit or receive */
@@ -376,9 +377,9 @@ AT91S_DataFlashStatus AT91F_WriteBufferToMain (
if (pDataFlash->pDevice->pages_number >= 16384)
cmdsize = 5;
/* Send the command to the dataflash */
- return(AT91F_DataFlashSendCommand (pDataFlash, BufferCommand, cmdsize,
- dest)); }
-
+ return (AT91F_DataFlashSendCommand(pDataFlash, BufferCommand,
+ cmdsize, dest));
+}
/*---------------------------------------------------------------------------*/
/* Function Name : AT91F_PartialPageWrite */
@@ -387,11 +388,10 @@ AT91S_DataFlashStatus AT91F_WriteBufferToMain (
/* : <AdrInpage> = adr to begin the fading */
/* : <length> = Number of bytes to erase */
/*---------------------------------------------------------------------------*/
-AT91S_DataFlashStatus AT91F_PartialPageWrite (
- AT91PS_DataFlash pDataFlash,
- unsigned char *src,
- unsigned int dest,
- unsigned int size)
+AT91S_DataFlashStatus AT91F_PartialPageWrite(AT91PS_DataFlash pDataFlash,
+ unsigned char *src,
+ unsigned int dest,
+ unsigned int size)
{
unsigned int page;
unsigned int AdrInPage;
@@ -400,10 +400,9 @@ AT91S_DataFlashStatus AT91F_PartialPageWrite (
AdrInPage = dest % (pDataFlash->pDevice->pages_size);
/* Read the contents of the page in the Sram Buffer */
- AT91F_MainMemoryToBufferTransfert(pDataFlash,
- DB_PAGE_2_BUF1_TRF, page);
+ AT91F_MainMemoryToBufferTransfert(pDataFlash, DB_PAGE_2_BUF1_TRF, page);
AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc,
- AT91C_TIMEOUT_WRDY);
+ AT91C_TIMEOUT_WRDY);
/*Update the SRAM buffer */
AT91F_DataFlashWriteBuffer(pDataFlash, DB_BUF1_WRITE, src,
AdrInPage, size);
@@ -416,12 +415,13 @@ AT91S_DataFlashStatus AT91F_PartialPageWrite (
AT91F_PageErase(pDataFlash, page);
/* Rewrite the modified Sram Buffer in the main memory */
AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc,
- AT91C_TIMEOUT_WRDY);
+ AT91C_TIMEOUT_WRDY);
}
/* Rewrite the modified Sram Buffer in the main memory */
- return(AT91F_WriteBufferToMain(pDataFlash, DB_BUF1_PAGE_ERASE_PGM,
- (page*pDataFlash->pDevice->pages_size)));
+ return (AT91F_WriteBufferToMain(pDataFlash, DB_BUF1_PAGE_ERASE_PGM,
+ (page *
+ pDataFlash->pDevice->pages_size)));
}
/*---------------------------------------------------------------------------*/
@@ -431,11 +431,9 @@ AT91S_DataFlashStatus AT91F_PartialPageWrite (
/* : <dest> = dataflash adress */
/* : <size> = data buffer size */
/*---------------------------------------------------------------------------*/
-AT91S_DataFlashStatus AT91F_DataFlashWrite(
- AT91PS_DataFlash pDataFlash,
- unsigned char *src,
- int dest,
- int size )
+AT91S_DataFlashStatus AT91F_DataFlashWrite(AT91PS_DataFlash pDataFlash,
+ unsigned char *src,
+ int dest, int size)
{
unsigned int length;
unsigned int page;
@@ -443,26 +441,24 @@ AT91S_DataFlashStatus AT91F_DataFlashWrite(
AT91F_SpiEnable(pDataFlash->pDevice->cs);
- if ( (dest + size) > (pDataFlash->pDevice->pages_size *
- (pDataFlash->pDevice->pages_number)))
+ if ((dest + size) > (pDataFlash->pDevice->pages_size *
+ (pDataFlash->pDevice->pages_number)))
return DATAFLASH_MEMORY_OVERFLOW;
/* If destination does not fit a page start address */
- if ((dest % ((unsigned int)(pDataFlash->pDevice->pages_size))) != 0 )
- {
- length = pDataFlash->pDevice->pages_size -
- (dest %
- ((unsigned int)
- (pDataFlash->pDevice->pages_size)));
+ if ((dest % ((unsigned int)(pDataFlash->pDevice->pages_size))) != 0) {
+ length =
+ pDataFlash->pDevice->pages_size -
+ (dest % ((unsigned int)(pDataFlash->pDevice->pages_size)));
if (size < length)
length = size;
- if(!AT91F_PartialPageWrite(pDataFlash,src, dest, length))
+ if (!AT91F_PartialPageWrite(pDataFlash, src, dest, length))
return DATAFLASH_ERROR;
AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc,
- AT91C_TIMEOUT_WRDY);
+ AT91C_TIMEOUT_WRDY);
/* Update size, source and destination pointers */
size -= length;
@@ -470,78 +466,77 @@ AT91S_DataFlashStatus AT91F_DataFlashWrite(
src += length;
}
- while (( size - pDataFlash->pDevice->pages_size ) >= 0 ) {
+ while ((size - pDataFlash->pDevice->pages_size) >= 0) {
/* program dataflash page */
page = (unsigned int)dest / (pDataFlash->pDevice->pages_size);
status = AT91F_DataFlashWriteBuffer(pDataFlash,
- DB_BUF1_WRITE, src, 0,
- pDataFlash->pDevice->pages_size);
+ DB_BUF1_WRITE, src, 0,
+ pDataFlash->pDevice->
+ pages_size);
AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc,
- AT91C_TIMEOUT_WRDY);
+ AT91C_TIMEOUT_WRDY);
status = AT91F_PageErase(pDataFlash, page);
AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc,
- AT91C_TIMEOUT_WRDY);
+ AT91C_TIMEOUT_WRDY);
if (!status)
return DATAFLASH_ERROR;
- status = AT91F_WriteBufferToMain (pDataFlash,
- DB_BUF1_PAGE_PGM, dest);
- if(!status)
+ status = AT91F_WriteBufferToMain(pDataFlash,
+ DB_BUF1_PAGE_PGM, dest);
+ if (!status)
return DATAFLASH_ERROR;
AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc,
- AT91C_TIMEOUT_WRDY);
+ AT91C_TIMEOUT_WRDY);
/* Update size, source and destination pointers */
size -= pDataFlash->pDevice->pages_size;
dest += pDataFlash->pDevice->pages_size;
- src += pDataFlash->pDevice->pages_size;
+ src += pDataFlash->pDevice->pages_size;
}
/* If still some bytes to read */
- if ( size > 0 ) {
+ if (size > 0) {
/* program dataflash page */
- if(!AT91F_PartialPageWrite(pDataFlash, src, dest, size) )
+ if (!AT91F_PartialPageWrite(pDataFlash, src, dest, size))
return DATAFLASH_ERROR;
AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc,
- AT91C_TIMEOUT_WRDY);
+ AT91C_TIMEOUT_WRDY);
}
return DATAFLASH_OK;
}
-
/*---------------------------------------------------------------------------*/
/* Function Name : AT91F_DataFlashRead */
/* Object : Read a block in dataflash */
/* Input Parameters : */
/* Return value : */
/*---------------------------------------------------------------------------*/
-int AT91F_DataFlashRead(
- AT91PS_DataFlash pDataFlash,
- unsigned long addr,
- unsigned long size,
- char *buffer)
+int AT91F_DataFlashRead(AT91PS_DataFlash pDataFlash,
+ unsigned long addr, unsigned long size, char *buffer)
{
unsigned long SizeToRead;
AT91F_SpiEnable(pDataFlash->pDevice->cs);
- if(AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc,
+ if (AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc,
AT91C_TIMEOUT_WRDY) != DATAFLASH_OK)
return -1;
while (size) {
- SizeToRead = (size < 0x8000)? size:0x8000;
+ SizeToRead = (size < 0x8000) ? size : 0x8000;
if (AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc,
- AT91C_TIMEOUT_WRDY) != DATAFLASH_OK)
+ AT91C_TIMEOUT_WRDY) !=
+ DATAFLASH_OK)
return -1;
- if (AT91F_DataFlashContinuousRead (pDataFlash, addr,
- (uchar *) buffer, SizeToRead) != DATAFLASH_OK)
+ if (AT91F_DataFlashContinuousRead(pDataFlash, addr,
+ (uchar *) buffer,
+ SizeToRead) != DATAFLASH_OK)
return -1;
size -= SizeToRead;
@@ -558,9 +553,10 @@ int AT91F_DataFlashRead(
/* Input Parameters : */
/* Return value : Dataflash status register */
/*---------------------------------------------------------------------------*/
-int AT91F_DataflashProbe(int cs, AT91PS_DataflashDesc pDesc) {
+int AT91F_DataflashProbe(int cs, AT91PS_DataflashDesc pDesc)
+{
AT91F_SpiEnable(cs);
AT91F_DataFlashGetStatus(pDesc);
- return((pDesc->command[1] == 0xFF)? 0: pDesc->command[1] & 0x3C);
+ return ((pDesc->command[1] == 0xFF) ? 0 : pDesc->command[1] & 0x3C);
}
#endif
diff --git a/drivers/ati_radeon_fb.c b/drivers/ati_radeon_fb.c
index c174f37b3f..9613d80cc8 100644
--- a/drivers/ati_radeon_fb.c
+++ b/drivers/ati_radeon_fb.c
@@ -300,7 +300,7 @@ typedef struct {
u32 val;
} reg_val;
-
+#if 0 /* unused ? -> scheduled for removal */
/* these common regs are cleared before mode setting so they do not
* interfere with anything
*/
@@ -316,11 +316,10 @@ static reg_val common_regs[] = {
{ CAP0_TRIG_CNTL, 0 },
{ CAP1_TRIG_CNTL, 0 },
};
-
+#endif /* 0 */
void radeon_setmode(void)
{
- int i;
struct radeon_regs *mode = malloc(sizeof(struct radeon_regs));
mode->crtc_gen_cntl = 0x03000200;
@@ -351,6 +350,9 @@ void radeon_setmode(void)
radeon_write_pll_regs(rinfo, mode);
}
+#include "bios_emulator/include/biosemu.h"
+extern int BootVideoCardBIOS(pci_dev_t pcidev, BE_VGAInfo ** pVGAInfo, int cleanUp);
+
int radeon_probe(struct radeonfb_info *rinfo)
{
pci_dev_t pdev;
diff --git a/drivers/bios_emulator/besys.c b/drivers/bios_emulator/besys.c
index 8f1d8b29d5..cb1b0c1b95 100644
--- a/drivers/bios_emulator/besys.c
+++ b/drivers/bios_emulator/besys.c
@@ -96,7 +96,7 @@ static u8 *BE_memaddr(u32 addr)
else if (addr >= 0xFFFF5 && addr < 0xFFFFE) {
/* Return a faked BIOS date string for non-x86 machines */
DB(printf("BE_memaddr - Returning BIOS date\n");)
- return BE_biosDate + addr - 0xFFFF5;
+ return (u8 *)(BE_biosDate + addr - 0xFFFF5);
} else if (addr == 0xFFFFE) {
/* Return system model identifier for non-x86 machines */
DB(printf("BE_memaddr - Returning model\n");)
diff --git a/drivers/bios_emulator/biosemu.c b/drivers/bios_emulator/biosemu.c
index ccfc872f78..75ceb458cf 100644
--- a/drivers/bios_emulator/biosemu.c
+++ b/drivers/bios_emulator/biosemu.c
@@ -96,7 +96,7 @@ int X86API BE_init(u32 debugFlags, int memSize, BE_VGAInfo * info, int shared)
return 0;
}
- M.mem_base = (unsigned long)malloc(memSize);
+ M.mem_base = malloc(memSize);
if (M.mem_base == NULL){
printf("Biosemu:Out of memory!");
@@ -106,7 +106,7 @@ int X86API BE_init(u32 debugFlags, int memSize, BE_VGAInfo * info, int shared)
_BE_env.emulateVGA = 0;
_BE_env.busmem_base = (unsigned long)malloc(128 * 1024);
- if (_BE_env.busmem_base == NULL){
+ if ((void *)_BE_env.busmem_base == NULL){
printf("Biosemu:Out of memory!");
return 0;
}
@@ -230,7 +230,7 @@ Cleans up and exits the emulator.
void X86API BE_exit(void)
{
free(M.mem_base);
- free(_BE_env.busmem_base);
+ free((void *)_BE_env.busmem_base);
}
/****************************************************************************
diff --git a/drivers/ds1722.c b/drivers/ds1722.c
index 227d8169a5..c19ee01393 100644
--- a/drivers/ds1722.c
+++ b/drivers/ds1722.c
@@ -1,10 +1,10 @@
#include <common.h>
-#include <ssi.h>
-
#ifdef CONFIG_DS1722
+#include <ssi.h>
+
static void ds1722_select(int dev)
{
ssi_set_interface(4096, 0, 0, 0);
diff --git a/drivers/fsl_pci_init.c b/drivers/fsl_pci_init.c
index 3a13eea1f2..1e778844a5 100644
--- a/drivers/fsl_pci_init.c
+++ b/drivers/fsl_pci_init.c
@@ -54,6 +54,7 @@ fsl_pci_init(struct pci_controller *hose)
u8 temp8;
int r;
int bridge;
+ int inbound = 0;
volatile ccsr_fsl_pci_t *pci = (ccsr_fsl_pci_t *) hose->cfg_addr;
pci_dev_t dev = PCI_BDF(busno,0,0);
@@ -74,6 +75,7 @@ fsl_pci_init(struct pci_controller *hose)
PIWAR_READ_SNOOP | PIWAR_WRITE_SNOOP |
(__ilog2(hose->regions[r].size) - 1);
pi++;
+ inbound = hose->regions[r].size > 0;
} else { /* Outbound */
po->powbar = (hose->regions[r].phys_start >> 12) & 0x000fffff;
po->potar = (hose->regions[r].bus_start >> 12) & 0x000fffff;
@@ -138,6 +140,12 @@ fsl_pci_init(struct pci_controller *hose)
pciauto_setup_device(hose, dev, 0, hose->pci_mem,
hose->pci_prefetch, hose->pci_io);
+ if (inbound) {
+ pci_hose_read_config_word(hose, dev, PCI_COMMAND, &temp16);
+ pci_hose_write_config_word(hose, dev, PCI_COMMAND,
+ temp16 | PCI_COMMAND_MEMORY);
+ }
+
#ifndef CONFIG_PCI_NOSCAN
printf (" Scanning PCI bus %02x\n", hose->current_busno);
hose->last_busno = pci_hose_scan_bus(hose,hose->current_busno);
diff --git a/drivers/isp116x-hcd.c b/drivers/isp116x-hcd.c
index 8e2bc7adcc..b21af10d0b 100644
--- a/drivers/isp116x-hcd.c
+++ b/drivers/isp116x-hcd.c
@@ -113,9 +113,9 @@ static const char hcd_name[] = "isp116x-hcd";
struct isp116x isp116x_dev;
struct isp116x_platform_data isp116x_board;
-int got_rhsc = 0; /* root hub status change */
+static int got_rhsc; /* root hub status change */
struct usb_device *devgone; /* device which was disconnected */
-int rh_devnum = 0; /* address of Root Hub endpoint */
+static int rh_devnum; /* address of Root Hub endpoint */
/* ------------------------------------------------------------------------- */
@@ -522,11 +522,13 @@ static int unpack_fifo(struct isp116x *isp116x, struct usb_device *dev,
done += PTD_GET_LEN(&ptd[i]);
cc = PTD_GET_CC(&ptd[i]);
- if (cc == TD_DATAUNDERRUN) { /* underrun is no error... */
- DBG("allowed data underrun");
- cc = TD_CC_NOERROR;
- }
- if (cc != TD_CC_NOERROR && ret == TD_CC_NOERROR)
+
+ /* Data underrun means basically that we had more buffer space than
+ * the function had data. It is perfectly normal but upper levels have
+ * to know how much we actually transferred.
+ */
+ if (cc == TD_NOTACCESSED ||
+ (cc != TD_CC_NOERROR && (ret == TD_CC_NOERROR || ret == TD_DATAUNDERRUN)))
ret = cc;
}
@@ -592,11 +594,19 @@ static int isp116x_interrupt(struct isp116x *isp116x)
return ret;
}
-#define PTD_NUM 64 /* it should be enougth... */
-struct ptd ptd[PTD_NUM];
+/* With one PTD we can transfer almost 1K in one go;
+ * HC does the splitting into endpoint digestible transactions
+ */
+struct ptd ptd[1];
+
static inline int max_transfer_len(struct usb_device *dev, unsigned long pipe)
{
- return min(PTD_NUM * usb_maxpacket(dev, pipe), PTD_NUM * 16);
+ unsigned mpck = usb_maxpacket(dev, pipe);
+
+ /* One PTD can transfer 1023 bytes but try to always
+ * transfer multiples of endpoint buffer size
+ */
+ return 1023 / mpck * mpck;
}
/* Do an USB transfer
@@ -610,13 +620,21 @@ static int isp116x_submit_job(struct usb_device *dev, unsigned long pipe,
int max = usb_maxpacket(dev, pipe);
int dir_out = usb_pipeout(pipe);
int speed_low = usb_pipeslow(pipe);
- int i, done, stat, timeout, cc;
- int retries = 10;
+ int i, done = 0, stat, timeout, cc;
+
+ /* 500 frames or 0.5s timeout when function is busy and NAKs transactions for a while */
+ int retries = 500;
DBG("------------------------------------------------");
dump_msg(dev, pipe, buffer, len, "SUBMIT");
DBG("------------------------------------------------");
+ if (len >= 1024) {
+ ERR("Too big job");
+ dev->status = USB_ST_CRC_ERR;
+ return -1;
+ }
+
if (isp116x->disabled) {
ERR("EPIPE");
dev->status = USB_ST_CRC_ERR;
@@ -653,29 +671,15 @@ static int isp116x_submit_job(struct usb_device *dev, unsigned long pipe,
isp116x_write_reg32(isp116x, HCINTSTAT, 0xff);
/* Prepare the PTD data */
- done = 0;
- i = 0;
- do {
- ptd[i].count = PTD_CC_MSK | PTD_ACTIVE_MSK |
- PTD_TOGGLE(usb_gettoggle(dev, epnum, dir_out));
- ptd[i].mps = PTD_MPS(max) | PTD_SPD(speed_low) | PTD_EP(epnum);
- ptd[i].len = PTD_LEN(max > len - done ? len - done : max) |
- PTD_DIR(dir);
- ptd[i].faddr = PTD_FA(usb_pipedevice(pipe));
-
- usb_dotoggle(dev, epnum, dir_out);
- done += PTD_GET_LEN(&ptd[i]);
- i++;
- if (i >= PTD_NUM) {
- ERR("****** Cannot pack buffer! ******");
- dev->status = USB_ST_BUF_ERR;
- return -1;
- }
- } while (done < len);
- ptd[i - 1].mps |= PTD_LAST_MSK;
+ ptd->count = PTD_CC_MSK | PTD_ACTIVE_MSK |
+ PTD_TOGGLE(usb_gettoggle(dev, epnum, dir_out));
+ ptd->mps = PTD_MPS(max) | PTD_SPD(speed_low) | PTD_EP(epnum) | PTD_LAST_MSK;
+ ptd->len = PTD_LEN(len) | PTD_DIR(dir);
+ ptd->faddr = PTD_FA(usb_pipedevice(pipe));
+retry_same:
/* Pack data into FIFO ram */
- pack_fifo(isp116x, dev, pipe, ptd, i, buffer, len);
+ pack_fifo(isp116x, dev, pipe, ptd, 1, buffer, len);
#ifdef EXTRA_DELAY
wait_ms(EXTRA_DELAY);
#endif
@@ -738,17 +742,42 @@ static int isp116x_submit_job(struct usb_device *dev, unsigned long pipe,
}
/* Unpack data from FIFO ram */
- cc = unpack_fifo(isp116x, dev, pipe, ptd, i, buffer, len);
+ cc = unpack_fifo(isp116x, dev, pipe, ptd, 1, buffer, len);
+
+ i = PTD_GET_COUNT(ptd);
+ done += i;
+ buffer += i;
+ len -= i;
- /* Mmm... sometime we get 0x0f as cc which is a non sense!
- * Just retry the transfer...
+ /* There was some kind of real problem; Prepare the PTD again
+ * and retry from the failed transaction on
*/
- if (cc == 0x0f && retries-- > 0) {
- usb_dotoggle(dev, epnum, dir_out);
- goto retry;
+ if (cc && cc != TD_NOTACCESSED && cc != TD_DATAUNDERRUN) {
+ if (retries >= 100) {
+ retries -= 100;
+ /* The chip will have toggled the toggle bit for the failed
+ * transaction too. We have to toggle it back.
+ */
+ usb_settoggle(dev, epnum, dir_out, !PTD_GET_TOGGLE(ptd));
+ goto retry;
+ }
+ }
+ /* "Normal" errors; TD_NOTACCESSED would mean in effect that the function have NAKed
+ * the transactions from the first on for the whole frame. It may be busy and we retry
+ * with the same PTD. PTD_ACTIVE (and not TD_NOTACCESSED) would mean that some of the
+ * PTD didn't make it because the function was busy or the frame ended before the PTD
+ * finished. We prepare the rest of the data and try again.
+ */
+ else if (cc == TD_NOTACCESSED || PTD_GET_ACTIVE(ptd) || (cc != TD_DATAUNDERRUN && PTD_GET_COUNT(ptd) < PTD_GET_LEN(ptd))) {
+ if (retries) {
+ --retries;
+ if (cc == TD_NOTACCESSED && PTD_GET_ACTIVE(ptd) && !PTD_GET_COUNT(ptd)) goto retry_same;
+ usb_settoggle(dev, epnum, dir_out, PTD_GET_TOGGLE(ptd));
+ goto retry;
+ }
}
- if (cc != TD_CC_NOERROR) {
+ if (cc != TD_CC_NOERROR && cc != TD_DATAUNDERRUN) {
DBG("****** completition code error %x ******", cc);
switch (cc) {
case TD_CC_BITSTUFFING:
@@ -766,6 +795,7 @@ static int isp116x_submit_job(struct usb_device *dev, unsigned long pipe,
}
return -cc;
}
+ else usb_settoggle(dev, epnum, dir_out, PTD_GET_TOGGLE(ptd));
dump_msg(dev, pipe, buffer, len, "SUBMIT(ret)");
@@ -1369,6 +1399,8 @@ int usb_lowlevel_init(void)
DBG("");
+ got_rhsc = rh_devnum = 0;
+
/* Init device registers addr */
isp116x->addr_reg = (u16 *) ISP116X_HCD_ADDR;
isp116x->data_reg = (u16 *) ISP116X_HCD_DATA;
diff --git a/drivers/mw_eeprom.c b/drivers/mw_eeprom.c
index 2a1f489842..2b3348810d 100644
--- a/drivers/mw_eeprom.c
+++ b/drivers/mw_eeprom.c
@@ -1,11 +1,11 @@
/* Three-wire (MicroWire) serial eeprom driver (for 93C46 and compatibles) */
#include <common.h>
-#include <ssi.h>
-
#ifdef CONFIG_MW_EEPROM
+#include <ssi.h>
+
/*
* Serial EEPROM opcodes, including start bit
*/
diff --git a/drivers/nand/Makefile b/drivers/nand/Makefile
index fb0185b991..42864f98f4 100644
--- a/drivers/nand/Makefile
+++ b/drivers/nand/Makefile
@@ -25,8 +25,14 @@ include $(TOPDIR)/config.mk
LIB := $(obj)libnand.a
-COBJS := nand.o nand_base.o nand_ids.o nand_ecc.o nand_bbt.o nand_util.o
-
+COBJS-y += nand.o
+COBJS-y += nand_base.o
+COBJS-y += nand_ids.o
+COBJS-y += nand_ecc.o
+COBJS-y += nand_bbt.o
+COBJS-y += nand_util.o
+
+COBJS := $(COBJS-y)
SRCS := $(COBJS:.o=.c)
OBJS := $(addprefix $(obj),$(COBJS))
diff --git a/drivers/ne2000.c b/drivers/ne2000.c
index b7ed876165..c978d62ef3 100644
--- a/drivers/ne2000.c
+++ b/drivers/ne2000.c
@@ -723,7 +723,8 @@ static hw_info_t hw_info[] = {
{ /* SuperSocket RE450T */ 0x0110, 0x00, 0xe0, 0x98, 0 },
{ /* Volktek NPL-402CT */ 0x0060, 0x00, 0x40, 0x05, 0 },
{ /* NEC PC-9801N-J12 */ 0x0ff0, 0x00, 0x00, 0x4c, 0 },
- { /* PCMCIA Technology OEM */ 0x01c8, 0x00, 0xa0, 0x0c, 0 }
+ { /* PCMCIA Technology OEM */ 0x01c8, 0x00, 0xa0, 0x0c, 0 },
+ { /* Qemu */ 0x0, 0x52, 0x54, 0x00, 0 }
};
#define NR_INFO (sizeof(hw_info)/sizeof(hw_info_t))
@@ -745,17 +746,15 @@ static void pcnet_reset_8390(void)
PRINTK("nic base is %lx\n", nic_base);
-#if 1
n2k_outb(E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD);
PRINTK("cmd (at %lx) is %x\n", nic_base+ E8390_CMD, n2k_inb(E8390_CMD));
n2k_outb(E8390_NODMA+E8390_PAGE1+E8390_STOP, E8390_CMD);
PRINTK("cmd (at %lx) is %x\n", nic_base+ E8390_CMD, n2k_inb(E8390_CMD));
n2k_outb(E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD);
PRINTK("cmd (at %lx) is %x\n", nic_base+ E8390_CMD, n2k_inb(E8390_CMD));
-#endif
n2k_outb(E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD);
- n2k_outb(n2k_inb(nic_base + PCNET_RESET), PCNET_RESET);
+ n2k_outb(n2k_inb(PCNET_RESET), PCNET_RESET);
for (i = 0; i < 100; i++) {
if ((r = (n2k_inb(EN0_ISR) & ENISR_RESET)) != 0)
@@ -826,27 +825,22 @@ static hw_info_t * get_prom(void ) {
/* U-boot specific routines */
-#define NB 5
static unsigned char *pbuf = NULL;
-static int plen[NB];
-static int nrx = 0;
static int pkey = -1;
+static int initialized=0;
void uboot_push_packet_len(int len) {
- PRINTK("pushed len = %d, nrx = %d\n", len, nrx);
+ PRINTK("pushed len = %d\n", len);
if (len>=2000) {
printf("NE2000: packet too big\n");
return;
}
- if (nrx >= NB) {
- printf("losing packets in rx\n");
- return;
- }
- plen[nrx] = len;
- dp83902a_recv(&pbuf[nrx*2000], len);
- nrx++;
+ dp83902a_recv(&pbuf[0], len);
+
+ /*Just pass it to the upper layer*/
+ NetReceive(&pbuf[0], len);
}
void uboot_push_tx_done(int key, int val) {
@@ -861,9 +855,9 @@ int eth_init(bd_t *bd) {
PRINTK("### eth_init\n");
if (!pbuf) {
- pbuf = malloc(NB*2000);
+ pbuf = malloc(2000);
if (!pbuf) {
- printf("Cannot allocate rx buffers\n");
+ printf("Cannot allocate rx buffer\n");
return -1;
}
}
@@ -903,37 +897,21 @@ int eth_init(bd_t *bd) {
if (dp83902a_init() == false)
return -1;
dp83902a_start(dev_addr);
+ initialized=1;
return 0;
}
void eth_halt() {
PRINTK("### eth_halt\n");
-
- dp83902a_stop();
+ if(initialized)
+ dp83902a_stop();
+ initialized=0;
}
int eth_rx() {
- int j, tmo;
-
- PRINTK("### eth_rx\n");
-
- tmo = get_timer (0) + TOUT * CFG_HZ;
- while(1) {
- dp83902a_poll();
- if (nrx > 0) {
- for(j=0; j<nrx; j++) {
- NetReceive(&pbuf[j*2000], plen[j]);
- }
- nrx = 0;
- return 1;
- }
- if (get_timer (0) >= tmo) {
- printf("timeout during rx\n");
- return 0;
- }
- }
- return 0;
+dp83902a_poll();
+return 1;
}
int eth_send(volatile void *packet, int length) {
@@ -959,5 +937,4 @@ int eth_send(volatile void *packet, int length) {
}
return 0;
}
-
#endif
diff --git a/drivers/ne2000.h b/drivers/ne2000.h
index 2955533d7a..c13d9f0bbb 100644
--- a/drivers/ne2000.h
+++ b/drivers/ne2000.h
@@ -42,7 +42,7 @@ are GPL, so this is, of course, GPL.
this file might be covered by the GNU General Public License.
Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
- at http://sources.redhat.com/ecos/ecos-license/ */
+ at http://sources.redhat.com/ecos/ecos-license/
-------------------------------------------
####ECOSGPLCOPYRIGHTEND####
####BSDCOPYRIGHTBEGIN####
diff --git a/drivers/onenand/Makefile b/drivers/onenand/Makefile
new file mode 100644
index 0000000000..2049413327
--- /dev/null
+++ b/drivers/onenand/Makefile
@@ -0,0 +1,44 @@
+#
+# Copyright (C) 2005-2007 Samsung Electronics.
+# Kyungmin Park <kyungmin.park@samsung.com>
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB := $(obj)libonenand.a
+
+COBJS := onenand_base.o onenand_bbt.o
+
+SRCS := $(COBJS:.o=.c)
+OBJS := $(addprefix $(obj),$(COBJS))
+
+all: $(LIB)
+
+$(LIB): $(obj).depend $(OBJS)
+ $(AR) $(ARFLAGS) $@ $(OBJS)
+
+#########################################################################
+
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/drivers/onenand/onenand_base.c b/drivers/onenand/onenand_base.c
new file mode 100644
index 0000000000..7983a4a0d8
--- /dev/null
+++ b/drivers/onenand/onenand_base.c
@@ -0,0 +1,1294 @@
+/*
+ * linux/drivers/mtd/onenand/onenand_base.c
+ *
+ * Copyright (C) 2005-2007 Samsung Electronics
+ * Kyungmin Park <kyungmin.park@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <common.h>
+
+#ifdef CONFIG_CMD_ONENAND
+
+#include <linux/mtd/compat.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/onenand.h>
+
+#include <asm/io.h>
+#include <asm/errno.h>
+
+static const unsigned char ffchars[] = {
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 16 */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 32 */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 48 */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 64 */
+};
+
+/**
+ * onenand_readw - [OneNAND Interface] Read OneNAND register
+ * @param addr address to read
+ *
+ * Read OneNAND register
+ */
+static unsigned short onenand_readw(void __iomem * addr)
+{
+ return readw(addr);
+}
+
+/**
+ * onenand_writew - [OneNAND Interface] Write OneNAND register with value
+ * @param value value to write
+ * @param addr address to write
+ *
+ * Write OneNAND register with value
+ */
+static void onenand_writew(unsigned short value, void __iomem * addr)
+{
+ writew(value, addr);
+}
+
+/**
+ * onenand_block_address - [DEFAULT] Get block address
+ * @param device the device id
+ * @param block the block
+ * @return translated block address if DDP, otherwise same
+ *
+ * Setup Start Address 1 Register (F100h)
+ */
+static int onenand_block_address(int device, int block)
+{
+ if (device & ONENAND_DEVICE_IS_DDP) {
+ /* Device Flash Core select, NAND Flash Block Address */
+ int dfs = 0, density, mask;
+
+ density = device >> ONENAND_DEVICE_DENSITY_SHIFT;
+ mask = (1 << (density + 6));
+
+ if (block & mask)
+ dfs = 1;
+
+ return (dfs << ONENAND_DDP_SHIFT) | (block & (mask - 1));
+ }
+
+ return block;
+}
+
+/**
+ * onenand_bufferram_address - [DEFAULT] Get bufferram address
+ * @param device the device id
+ * @param block the block
+ * @return set DBS value if DDP, otherwise 0
+ *
+ * Setup Start Address 2 Register (F101h) for DDP
+ */
+static int onenand_bufferram_address(int device, int block)
+{
+ if (device & ONENAND_DEVICE_IS_DDP) {
+ /* Device BufferRAM Select */
+ int dbs = 0, density, mask;
+
+ density = device >> ONENAND_DEVICE_DENSITY_SHIFT;
+ mask = (1 << (density + 6));
+
+ if (block & mask)
+ dbs = 1;
+
+ return (dbs << ONENAND_DDP_SHIFT);
+ }
+
+ return 0;
+}
+
+/**
+ * onenand_page_address - [DEFAULT] Get page address
+ * @param page the page address
+ * @param sector the sector address
+ * @return combined page and sector address
+ *
+ * Setup Start Address 8 Register (F107h)
+ */
+static int onenand_page_address(int page, int sector)
+{
+ /* Flash Page Address, Flash Sector Address */
+ int fpa, fsa;
+
+ fpa = page & ONENAND_FPA_MASK;
+ fsa = sector & ONENAND_FSA_MASK;
+
+ return ((fpa << ONENAND_FPA_SHIFT) | fsa);
+}
+
+/**
+ * onenand_buffer_address - [DEFAULT] Get buffer address
+ * @param dataram1 DataRAM index
+ * @param sectors the sector address
+ * @param count the number of sectors
+ * @return the start buffer value
+ *
+ * Setup Start Buffer Register (F200h)
+ */
+static int onenand_buffer_address(int dataram1, int sectors, int count)
+{
+ int bsa, bsc;
+
+ /* BufferRAM Sector Address */
+ bsa = sectors & ONENAND_BSA_MASK;
+
+ if (dataram1)
+ bsa |= ONENAND_BSA_DATARAM1; /* DataRAM1 */
+ else
+ bsa |= ONENAND_BSA_DATARAM0; /* DataRAM0 */
+
+ /* BufferRAM Sector Count */
+ bsc = count & ONENAND_BSC_MASK;
+
+ return ((bsa << ONENAND_BSA_SHIFT) | bsc);
+}
+
+/**
+ * onenand_command - [DEFAULT] Send command to OneNAND device
+ * @param mtd MTD device structure
+ * @param cmd the command to be sent
+ * @param addr offset to read from or write to
+ * @param len number of bytes to read or write
+ *
+ * Send command to OneNAND device. This function is used for middle/large page
+ * devices (1KB/2KB Bytes per page)
+ */
+static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr,
+ size_t len)
+{
+ struct onenand_chip *this = mtd->priv;
+ int value, readcmd = 0;
+ int block, page;
+ /* Now we use page size operation */
+ int sectors = 4, count = 4;
+
+ /* Address translation */
+ switch (cmd) {
+ case ONENAND_CMD_UNLOCK:
+ case ONENAND_CMD_LOCK:
+ case ONENAND_CMD_LOCK_TIGHT:
+ block = -1;
+ page = -1;
+ break;
+
+ case ONENAND_CMD_ERASE:
+ case ONENAND_CMD_BUFFERRAM:
+ block = (int)(addr >> this->erase_shift);
+ page = -1;
+ break;
+
+ default:
+ block = (int)(addr >> this->erase_shift);
+ page = (int)(addr >> this->page_shift);
+ page &= this->page_mask;
+ break;
+ }
+
+ /* NOTE: The setting order of the registers is very important! */
+ if (cmd == ONENAND_CMD_BUFFERRAM) {
+ /* Select DataRAM for DDP */
+ value = onenand_bufferram_address(this->device_id, block);
+ this->write_word(value,
+ this->base + ONENAND_REG_START_ADDRESS2);
+
+ /* Switch to the next data buffer */
+ ONENAND_SET_NEXT_BUFFERRAM(this);
+
+ return 0;
+ }
+
+ if (block != -1) {
+ /* Write 'DFS, FBA' of Flash */
+ value = onenand_block_address(this->device_id, block);
+ this->write_word(value,
+ this->base + ONENAND_REG_START_ADDRESS1);
+ }
+
+ if (page != -1) {
+ int dataram;
+
+ switch (cmd) {
+ case ONENAND_CMD_READ:
+ case ONENAND_CMD_READOOB:
+ dataram = ONENAND_SET_NEXT_BUFFERRAM(this);
+ readcmd = 1;
+ break;
+
+ default:
+ dataram = ONENAND_CURRENT_BUFFERRAM(this);
+ break;
+ }
+
+ /* Write 'FPA, FSA' of Flash */
+ value = onenand_page_address(page, sectors);
+ this->write_word(value,
+ this->base + ONENAND_REG_START_ADDRESS8);
+
+ /* Write 'BSA, BSC' of DataRAM */
+ value = onenand_buffer_address(dataram, sectors, count);
+ this->write_word(value, this->base + ONENAND_REG_START_BUFFER);
+
+ if (readcmd) {
+ /* Select DataRAM for DDP */
+ value =
+ onenand_bufferram_address(this->device_id, block);
+ this->write_word(value,
+ this->base +
+ ONENAND_REG_START_ADDRESS2);
+ }
+ }
+
+ /* Interrupt clear */
+ this->write_word(ONENAND_INT_CLEAR, this->base + ONENAND_REG_INTERRUPT);
+ /* Write command */
+ this->write_word(cmd, this->base + ONENAND_REG_COMMAND);
+
+ return 0;
+}
+
+/**
+ * onenand_wait - [DEFAULT] wait until the command is done
+ * @param mtd MTD device structure
+ * @param state state to select the max. timeout value
+ *
+ * Wait for command done. This applies to all OneNAND command
+ * Read can take up to 30us, erase up to 2ms and program up to 350us
+ * according to general OneNAND specs
+ */
+static int onenand_wait(struct mtd_info *mtd, int state)
+{
+ struct onenand_chip *this = mtd->priv;
+ unsigned int flags = ONENAND_INT_MASTER;
+ unsigned int interrupt = 0;
+ unsigned int ctrl, ecc;
+
+ while (1) {
+ interrupt = this->read_word(this->base + ONENAND_REG_INTERRUPT);
+ if (interrupt & flags)
+ break;
+ }
+
+ ctrl = this->read_word(this->base + ONENAND_REG_CTRL_STATUS);
+
+ if (ctrl & ONENAND_CTRL_ERROR) {
+ DEBUG(MTD_DEBUG_LEVEL0,
+ "onenand_wait: controller error = 0x%04x\n", ctrl);
+ return -EAGAIN;
+ }
+
+ if (ctrl & ONENAND_CTRL_LOCK) {
+ DEBUG(MTD_DEBUG_LEVEL0,
+ "onenand_wait: it's locked error = 0x%04x\n", ctrl);
+ return -EIO;
+ }
+
+ if (interrupt & ONENAND_INT_READ) {
+ ecc = this->read_word(this->base + ONENAND_REG_ECC_STATUS);
+ if (ecc & ONENAND_ECC_2BIT_ALL) {
+ DEBUG(MTD_DEBUG_LEVEL0,
+ "onenand_wait: ECC error = 0x%04x\n", ecc);
+ return -EBADMSG;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * onenand_bufferram_offset - [DEFAULT] BufferRAM offset
+ * @param mtd MTD data structure
+ * @param area BufferRAM area
+ * @return offset given area
+ *
+ * Return BufferRAM offset given area
+ */
+static inline int onenand_bufferram_offset(struct mtd_info *mtd, int area)
+{
+ struct onenand_chip *this = mtd->priv;
+
+ if (ONENAND_CURRENT_BUFFERRAM(this)) {
+ if (area == ONENAND_DATARAM)
+ return mtd->oobblock;
+ if (area == ONENAND_SPARERAM)
+ return mtd->oobsize;
+ }
+
+ return 0;
+}
+
+/**
+ * onenand_read_bufferram - [OneNAND Interface] Read the bufferram area
+ * @param mtd MTD data structure
+ * @param area BufferRAM area
+ * @param buffer the databuffer to put/get data
+ * @param offset offset to read from or write to
+ * @param count number of bytes to read/write
+ *
+ * Read the BufferRAM area
+ */
+static int onenand_read_bufferram(struct mtd_info *mtd, int area,
+ unsigned char *buffer, int offset,
+ size_t count)
+{
+ struct onenand_chip *this = mtd->priv;
+ void __iomem *bufferram;
+
+ bufferram = this->base + area;
+ bufferram += onenand_bufferram_offset(mtd, area);
+
+ memcpy(buffer, bufferram + offset, count);
+
+ return 0;
+}
+
+/**
+ * onenand_sync_read_bufferram - [OneNAND Interface] Read the bufferram area with Sync. Burst mode
+ * @param mtd MTD data structure
+ * @param area BufferRAM area
+ * @param buffer the databuffer to put/get data
+ * @param offset offset to read from or write to
+ * @param count number of bytes to read/write
+ *
+ * Read the BufferRAM area with Sync. Burst Mode
+ */
+static int onenand_sync_read_bufferram(struct mtd_info *mtd, int area,
+ unsigned char *buffer, int offset,
+ size_t count)
+{
+ struct onenand_chip *this = mtd->priv;
+ void __iomem *bufferram;
+
+ bufferram = this->base + area;
+ bufferram += onenand_bufferram_offset(mtd, area);
+
+ this->mmcontrol(mtd, ONENAND_SYS_CFG1_SYNC_READ);
+
+ memcpy(buffer, bufferram + offset, count);
+
+ this->mmcontrol(mtd, 0);
+
+ return 0;
+}
+
+/**
+ * onenand_write_bufferram - [OneNAND Interface] Write the bufferram area
+ * @param mtd MTD data structure
+ * @param area BufferRAM area
+ * @param buffer the databuffer to put/get data
+ * @param offset offset to read from or write to
+ * @param count number of bytes to read/write
+ *
+ * Write the BufferRAM area
+ */
+static int onenand_write_bufferram(struct mtd_info *mtd, int area,
+ const unsigned char *buffer, int offset,
+ size_t count)
+{
+ struct onenand_chip *this = mtd->priv;
+ void __iomem *bufferram;
+
+ bufferram = this->base + area;
+ bufferram += onenand_bufferram_offset(mtd, area);
+
+ memcpy(bufferram + offset, buffer, count);
+
+ return 0;
+}
+
+/**
+ * onenand_check_bufferram - [GENERIC] Check BufferRAM information
+ * @param mtd MTD data structure
+ * @param addr address to check
+ * @return 1 if there are valid data, otherwise 0
+ *
+ * Check bufferram if there is data we required
+ */
+static int onenand_check_bufferram(struct mtd_info *mtd, loff_t addr)
+{
+ struct onenand_chip *this = mtd->priv;
+ int block, page;
+ int i;
+
+ block = (int)(addr >> this->erase_shift);
+ page = (int)(addr >> this->page_shift);
+ page &= this->page_mask;
+
+ i = ONENAND_CURRENT_BUFFERRAM(this);
+
+ /* Is there valid data? */
+ if (this->bufferram[i].block == block &&
+ this->bufferram[i].page == page && this->bufferram[i].valid)
+ return 1;
+
+ return 0;
+}
+
+/**
+ * onenand_update_bufferram - [GENERIC] Update BufferRAM information
+ * @param mtd MTD data structure
+ * @param addr address to update
+ * @param valid valid flag
+ *
+ * Update BufferRAM information
+ */
+static int onenand_update_bufferram(struct mtd_info *mtd, loff_t addr,
+ int valid)
+{
+ struct onenand_chip *this = mtd->priv;
+ int block, page;
+ int i;
+
+ block = (int)(addr >> this->erase_shift);
+ page = (int)(addr >> this->page_shift);
+ page &= this->page_mask;
+
+ /* Invalidate BufferRAM */
+ for (i = 0; i < MAX_BUFFERRAM; i++) {
+ if (this->bufferram[i].block == block &&
+ this->bufferram[i].page == page)
+ this->bufferram[i].valid = 0;
+ }
+
+ /* Update BufferRAM */
+ i = ONENAND_CURRENT_BUFFERRAM(this);
+ this->bufferram[i].block = block;
+ this->bufferram[i].page = page;
+ this->bufferram[i].valid = valid;
+
+ return 0;
+}
+
+/**
+ * onenand_get_device - [GENERIC] Get chip for selected access
+ * @param mtd MTD device structure
+ * @param new_state the state which is requested
+ *
+ * Get the device and lock it for exclusive access
+ */
+static void onenand_get_device(struct mtd_info *mtd, int new_state)
+{
+ /* Do nothing */
+}
+
+/**
+ * onenand_release_device - [GENERIC] release chip
+ * @param mtd MTD device structure
+ *
+ * Deselect, release chip lock and wake up anyone waiting on the device
+ */
+static void onenand_release_device(struct mtd_info *mtd)
+{
+ /* Do nothing */
+}
+
+/**
+ * onenand_read_ecc - [MTD Interface] Read data with ECC
+ * @param mtd MTD device structure
+ * @param from offset to read from
+ * @param len number of bytes to read
+ * @param retlen pointer to variable to store the number of read bytes
+ * @param buf the databuffer to put data
+ * @param oob_buf filesystem supplied oob data buffer
+ * @param oobsel oob selection structure
+ *
+ * OneNAND read with ECC
+ */
+static int onenand_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
+ size_t * retlen, u_char * buf,
+ u_char * oob_buf, struct nand_oobinfo *oobsel)
+{
+ struct onenand_chip *this = mtd->priv;
+ int read = 0, column;
+ int thislen;
+ int ret = 0;
+
+ DEBUG(MTD_DEBUG_LEVEL3, "onenand_read_ecc: from = 0x%08x, len = %i\n",
+ (unsigned int)from, (int)len);
+
+ /* Do not allow reads past end of device */
+ if ((from + len) > mtd->size) {
+ DEBUG(MTD_DEBUG_LEVEL0,
+ "onenand_read_ecc: Attempt read beyond end of device\n");
+ *retlen = 0;
+ return -EINVAL;
+ }
+
+ /* Grab the lock and see if the device is available */
+ onenand_get_device(mtd, FL_READING);
+
+ while (read < len) {
+ thislen = min_t(int, mtd->oobblock, len - read);
+
+ column = from & (mtd->oobblock - 1);
+ if (column + thislen > mtd->oobblock)
+ thislen = mtd->oobblock - column;
+
+ if (!onenand_check_bufferram(mtd, from)) {
+ this->command(mtd, ONENAND_CMD_READ, from,
+ mtd->oobblock);
+ ret = this->wait(mtd, FL_READING);
+ /* First copy data and check return value for ECC handling */
+ onenand_update_bufferram(mtd, from, 1);
+ }
+
+ this->read_bufferram(mtd, ONENAND_DATARAM, buf, column,
+ thislen);
+
+ read += thislen;
+ if (read == len)
+ break;
+
+ if (ret) {
+ DEBUG(MTD_DEBUG_LEVEL0,
+ "onenand_read_ecc: read failed = %d\n", ret);
+ break;
+ }
+
+ from += thislen;
+ buf += thislen;
+ }
+
+ /* Deselect and wake up anyone waiting on the device */
+ onenand_release_device(mtd);
+
+ /*
+ * Return success, if no ECC failures, else -EBADMSG
+ * fs driver will take care of that, because
+ * retlen == desired len and result == -EBADMSG
+ */
+ *retlen = read;
+ return ret;
+}
+
+/**
+ * onenand_read - [MTD Interface] MTD compability function for onenand_read_ecc
+ * @param mtd MTD device structure
+ * @param from offset to read from
+ * @param len number of bytes to read
+ * @param retlen pointer to variable to store the number of read bytes
+ * @param buf the databuffer to put data
+ *
+ * This function simply calls onenand_read_ecc with oob buffer and oobsel = NULL
+*/
+int onenand_read(struct mtd_info *mtd, loff_t from, size_t len,
+ size_t * retlen, u_char * buf)
+{
+ return onenand_read_ecc(mtd, from, len, retlen, buf, NULL, NULL);
+}
+
+/**
+ * onenand_read_oob - [MTD Interface] OneNAND read out-of-band
+ * @param mtd MTD device structure
+ * @param from offset to read from
+ * @param len number of bytes to read
+ * @param retlen pointer to variable to store the number of read bytes
+ * @param buf the databuffer to put data
+ *
+ * OneNAND read out-of-band data from the spare area
+ */
+int onenand_read_oob(struct mtd_info *mtd, loff_t from, size_t len,
+ size_t * retlen, u_char * buf)
+{
+ struct onenand_chip *this = mtd->priv;
+ int read = 0, thislen, column;
+ int ret = 0;
+
+ DEBUG(MTD_DEBUG_LEVEL3, "onenand_read_oob: from = 0x%08x, len = %i\n",
+ (unsigned int)from, (int)len);
+
+ /* Initialize return length value */
+ *retlen = 0;
+
+ /* Do not allow reads past end of device */
+ if (unlikely((from + len) > mtd->size)) {
+ DEBUG(MTD_DEBUG_LEVEL0,
+ "onenand_read_oob: Attempt read beyond end of device\n");
+ return -EINVAL;
+ }
+
+ /* Grab the lock and see if the device is available */
+ onenand_get_device(mtd, FL_READING);
+
+ column = from & (mtd->oobsize - 1);
+
+ while (read < len) {
+ thislen = mtd->oobsize - column;
+ thislen = min_t(int, thislen, len);
+
+ this->command(mtd, ONENAND_CMD_READOOB, from, mtd->oobsize);
+
+ onenand_update_bufferram(mtd, from, 0);
+
+ ret = this->wait(mtd, FL_READING);
+ /* First copy data and check return value for ECC handling */
+
+ this->read_bufferram(mtd, ONENAND_SPARERAM, buf, column,
+ thislen);
+
+ read += thislen;
+ if (read == len)
+ break;
+
+ if (ret) {
+ DEBUG(MTD_DEBUG_LEVEL0,
+ "onenand_read_oob: read failed = %d\n", ret);
+ break;
+ }
+
+ buf += thislen;
+ /* Read more? */
+ if (read < len) {
+ /* Page size */
+ from += mtd->oobblock;
+ column = 0;
+ }
+ }
+
+ /* Deselect and wake up anyone waiting on the device */
+ onenand_release_device(mtd);
+
+ *retlen = read;
+ return ret;
+}
+
+#ifdef CONFIG_MTD_ONENAND_VERIFY_WRITE
+/**
+ * onenand_verify_page - [GENERIC] verify the chip contents after a write
+ * @param mtd MTD device structure
+ * @param buf the databuffer to verify
+ * @param block block address
+ * @param page page address
+ *
+ * Check DataRAM area directly
+ */
+static int onenand_verify_page(struct mtd_info *mtd, u_char * buf,
+ loff_t addr, int block, int page)
+{
+ struct onenand_chip *this = mtd->priv;
+ void __iomem *dataram0, *dataram1;
+ int ret = 0;
+
+ this->command(mtd, ONENAND_CMD_READ, addr, mtd->oobblock);
+
+ ret = this->wait(mtd, FL_READING);
+ if (ret)
+ return ret;
+
+ onenand_update_bufferram(mtd, addr, 1);
+
+ /* Check, if the two dataram areas are same */
+ dataram0 = this->base + ONENAND_DATARAM;
+ dataram1 = dataram0 + mtd->oobblock;
+
+ if (memcmp(dataram0, dataram1, mtd->oobblock))
+ return -EBADMSG;
+
+ return 0;
+}
+#else
+#define onenand_verify_page(...) (0)
+#endif
+
+#define NOTALIGNED(x) ((x & (mtd->oobblock - 1)) != 0)
+
+/**
+ * onenand_write_ecc - [MTD Interface] OneNAND write with ECC
+ * @param mtd MTD device structure
+ * @param to offset to write to
+ * @param len number of bytes to write
+ * @param retlen pointer to variable to store the number of written bytes
+ * @param buf the data to write
+ * @param eccbuf filesystem supplied oob data buffer
+ * @param oobsel oob selection structure
+ *
+ * OneNAND write with ECC
+ */
+static int onenand_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
+ size_t * retlen, const u_char * buf,
+ u_char * eccbuf, struct nand_oobinfo *oobsel)
+{
+ struct onenand_chip *this = mtd->priv;
+ int written = 0;
+ int ret = 0;
+
+ DEBUG(MTD_DEBUG_LEVEL3, "onenand_write_ecc: to = 0x%08x, len = %i\n",
+ (unsigned int)to, (int)len);
+
+ /* Initialize retlen, in case of early exit */
+ *retlen = 0;
+
+ /* Do not allow writes past end of device */
+ if (unlikely((to + len) > mtd->size)) {
+ DEBUG(MTD_DEBUG_LEVEL0,
+ "onenand_write_ecc: Attempt write to past end of device\n");
+ return -EINVAL;
+ }
+
+ /* Reject writes, which are not page aligned */
+ if (unlikely(NOTALIGNED(to)) || unlikely(NOTALIGNED(len))) {
+ DEBUG(MTD_DEBUG_LEVEL0,
+ "onenand_write_ecc: Attempt to write not page aligned data\n");
+ return -EINVAL;
+ }
+
+ /* Grab the lock and see if the device is available */
+ onenand_get_device(mtd, FL_WRITING);
+
+ /* Loop until all data write */
+ while (written < len) {
+ int thislen = min_t(int, mtd->oobblock, len - written);
+
+ this->command(mtd, ONENAND_CMD_BUFFERRAM, to, mtd->oobblock);
+
+ this->write_bufferram(mtd, ONENAND_DATARAM, buf, 0, thislen);
+ this->write_bufferram(mtd, ONENAND_SPARERAM, ffchars, 0,
+ mtd->oobsize);
+
+ this->command(mtd, ONENAND_CMD_PROG, to, mtd->oobblock);
+
+ onenand_update_bufferram(mtd, to, 1);
+
+ ret = this->wait(mtd, FL_WRITING);
+ if (ret) {
+ DEBUG(MTD_DEBUG_LEVEL0,
+ "onenand_write_ecc: write filaed %d\n", ret);
+ break;
+ }
+
+ written += thislen;
+
+ /* Only check verify write turn on */
+ ret = onenand_verify_page(mtd, (u_char *) buf, to, block, page);
+ if (ret) {
+ DEBUG(MTD_DEBUG_LEVEL0,
+ "onenand_write_ecc: verify failed %d\n", ret);
+ break;
+ }
+
+ if (written == len)
+ break;
+
+ to += thislen;
+ buf += thislen;
+ }
+
+ /* Deselect and wake up anyone waiting on the device */
+ onenand_release_device(mtd);
+
+ *retlen = written;
+
+ return ret;
+}
+
+/**
+ * onenand_write - [MTD Interface] compability function for onenand_write_ecc
+ * @param mtd MTD device structure
+ * @param to offset to write to
+ * @param len number of bytes to write
+ * @param retlen pointer to variable to store the number of written bytes
+ * @param buf the data to write
+ *
+ * This function simply calls onenand_write_ecc
+ * with oob buffer and oobsel = NULL
+ */
+int onenand_write(struct mtd_info *mtd, loff_t to, size_t len,
+ size_t * retlen, const u_char * buf)
+{
+ return onenand_write_ecc(mtd, to, len, retlen, buf, NULL, NULL);
+}
+
+/**
+ * onenand_write_oob - [MTD Interface] OneNAND write out-of-band
+ * @param mtd MTD device structure
+ * @param to offset to write to
+ * @param len number of bytes to write
+ * @param retlen pointer to variable to store the number of written bytes
+ * @param buf the data to write
+ *
+ * OneNAND write out-of-band
+ */
+int onenand_write_oob(struct mtd_info *mtd, loff_t to, size_t len,
+ size_t * retlen, const u_char * buf)
+{
+ struct onenand_chip *this = mtd->priv;
+ int column, status;
+ int written = 0;
+
+ DEBUG(MTD_DEBUG_LEVEL3, "onenand_write_oob: to = 0x%08x, len = %i\n",
+ (unsigned int)to, (int)len);
+
+ /* Initialize retlen, in case of early exit */
+ *retlen = 0;
+
+ /* Do not allow writes past end of device */
+ if (unlikely((to + len) > mtd->size)) {
+ DEBUG(MTD_DEBUG_LEVEL0,
+ "onenand_write_oob: Attempt write to past end of device\n");
+ return -EINVAL;
+ }
+
+ /* Grab the lock and see if the device is available */
+ onenand_get_device(mtd, FL_WRITING);
+
+ /* Loop until all data write */
+ while (written < len) {
+ int thislen = min_t(int, mtd->oobsize, len - written);
+
+ column = to & (mtd->oobsize - 1);
+
+ this->command(mtd, ONENAND_CMD_BUFFERRAM, to, mtd->oobsize);
+
+ this->write_bufferram(mtd, ONENAND_SPARERAM, ffchars, 0,
+ mtd->oobsize);
+ this->write_bufferram(mtd, ONENAND_SPARERAM, buf, column,
+ thislen);
+
+ this->command(mtd, ONENAND_CMD_PROGOOB, to, mtd->oobsize);
+
+ onenand_update_bufferram(mtd, to, 0);
+
+ status = this->wait(mtd, FL_WRITING);
+ if (status)
+ break;
+
+ written += thislen;
+ if (written == len)
+ break;
+
+ to += thislen;
+ buf += thislen;
+ }
+
+ /* Deselect and wake up anyone waiting on the device */
+ onenand_release_device(mtd);
+
+ *retlen = written;
+
+ return 0;
+}
+
+/**
+ * onenand_erase - [MTD Interface] erase block(s)
+ * @param mtd MTD device structure
+ * @param instr erase instruction
+ *
+ * Erase one ore more blocks
+ */
+int onenand_erase(struct mtd_info *mtd, struct erase_info *instr)
+{
+ struct onenand_chip *this = mtd->priv;
+ unsigned int block_size;
+ loff_t addr;
+ int len;
+ int ret = 0;
+
+ DEBUG(MTD_DEBUG_LEVEL3, "onenand_erase: start = 0x%08x, len = %i\n",
+ (unsigned int)instr->addr, (unsigned int)instr->len);
+
+ block_size = (1 << this->erase_shift);
+
+ /* Start address must align on block boundary */
+ if (unlikely(instr->addr & (block_size - 1))) {
+ DEBUG(MTD_DEBUG_LEVEL0, "onenand_erase: Unaligned address\n");
+ return -EINVAL;
+ }
+
+ /* Length must align on block boundary */
+ if (unlikely(instr->len & (block_size - 1))) {
+ DEBUG(MTD_DEBUG_LEVEL0,
+ "onenand_erase: Length not block aligned\n");
+ return -EINVAL;
+ }
+
+ /* Do not allow erase past end of device */
+ if (unlikely((instr->len + instr->addr) > mtd->size)) {
+ DEBUG(MTD_DEBUG_LEVEL0,
+ "onenand_erase: Erase past end of device\n");
+ return -EINVAL;
+ }
+
+ instr->fail_addr = 0xffffffff;
+
+ /* Grab the lock and see if the device is available */
+ onenand_get_device(mtd, FL_ERASING);
+
+ /* Loop throught the pages */
+ len = instr->len;
+ addr = instr->addr;
+
+ instr->state = MTD_ERASING;
+
+ while (len) {
+
+ /* TODO Check badblock */
+
+ this->command(mtd, ONENAND_CMD_ERASE, addr, block_size);
+
+ ret = this->wait(mtd, FL_ERASING);
+ /* Check, if it is write protected */
+ if (ret) {
+ if (ret == -EPERM)
+ DEBUG(MTD_DEBUG_LEVEL0,
+ "onenand_erase: Device is write protected!!!\n");
+ else
+ DEBUG(MTD_DEBUG_LEVEL0,
+ "onenand_erase: Failed erase, block %d\n",
+ (unsigned)(addr >> this->erase_shift));
+ instr->state = MTD_ERASE_FAILED;
+ instr->fail_addr = addr;
+ goto erase_exit;
+ }
+
+ len -= block_size;
+ addr += block_size;
+ }
+
+ instr->state = MTD_ERASE_DONE;
+
+ erase_exit:
+
+ ret = instr->state == MTD_ERASE_DONE ? 0 : -EIO;
+ /* Do call back function */
+ if (!ret)
+ mtd_erase_callback(instr);
+
+ /* Deselect and wake up anyone waiting on the device */
+ onenand_release_device(mtd);
+
+ return ret;
+}
+
+/**
+ * onenand_sync - [MTD Interface] sync
+ * @param mtd MTD device structure
+ *
+ * Sync is actually a wait for chip ready function
+ */
+void onenand_sync(struct mtd_info *mtd)
+{
+ DEBUG(MTD_DEBUG_LEVEL3, "onenand_sync: called\n");
+
+ /* Grab the lock and see if the device is available */
+ onenand_get_device(mtd, FL_SYNCING);
+
+ /* Release it and go back */
+ onenand_release_device(mtd);
+}
+
+/**
+ * onenand_block_isbad - [MTD Interface] Check whether the block at the given offset is bad
+ * @param mtd MTD device structure
+ * @param ofs offset relative to mtd start
+ */
+int onenand_block_isbad(struct mtd_info *mtd, loff_t ofs)
+{
+ /*
+ * TODO
+ * 1. Bad block table (BBT)
+ * -> using NAND BBT to support JFFS2
+ * 2. Bad block management (BBM)
+ * -> bad block replace scheme
+ *
+ * Currently we do nothing
+ */
+ return 0;
+}
+
+/**
+ * onenand_block_markbad - [MTD Interface] Mark the block at the given offset as bad
+ * @param mtd MTD device structure
+ * @param ofs offset relative to mtd start
+ */
+int onenand_block_markbad(struct mtd_info *mtd, loff_t ofs)
+{
+ /* see above */
+ return 0;
+}
+
+/**
+ * onenand_unlock - [MTD Interface] Unlock block(s)
+ * @param mtd MTD device structure
+ * @param ofs offset relative to mtd start
+ * @param len number of bytes to unlock
+ *
+ * Unlock one or more blocks
+ */
+int onenand_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
+{
+ struct onenand_chip *this = mtd->priv;
+ int start, end, block, value, status;
+
+ start = ofs >> this->erase_shift;
+ end = len >> this->erase_shift;
+
+ /* Continuous lock scheme */
+ if (this->options & ONENAND_CONT_LOCK) {
+ /* Set start block address */
+ this->write_word(start,
+ this->base + ONENAND_REG_START_BLOCK_ADDRESS);
+ /* Set end block address */
+ this->write_word(end - 1,
+ this->base + ONENAND_REG_END_BLOCK_ADDRESS);
+ /* Write unlock command */
+ this->command(mtd, ONENAND_CMD_UNLOCK, 0, 0);
+
+ /* There's no return value */
+ this->wait(mtd, FL_UNLOCKING);
+
+ /* Sanity check */
+ while (this->read_word(this->base + ONENAND_REG_CTRL_STATUS)
+ & ONENAND_CTRL_ONGO)
+ continue;
+
+ /* Check lock status */
+ status = this->read_word(this->base + ONENAND_REG_WP_STATUS);
+ if (!(status & ONENAND_WP_US))
+ printk(KERN_ERR "wp status = 0x%x\n", status);
+
+ return 0;
+ }
+
+ /* Block lock scheme */
+ for (block = start; block < end; block++) {
+ /* Set start block address */
+ this->write_word(block,
+ this->base + ONENAND_REG_START_BLOCK_ADDRESS);
+ /* Write unlock command */
+ this->command(mtd, ONENAND_CMD_UNLOCK, 0, 0);
+
+ /* There's no return value */
+ this->wait(mtd, FL_UNLOCKING);
+
+ /* Sanity check */
+ while (this->read_word(this->base + ONENAND_REG_CTRL_STATUS)
+ & ONENAND_CTRL_ONGO)
+ continue;
+
+ /* Set block address for read block status */
+ value = onenand_block_address(this->device_id, block);
+ this->write_word(value,
+ this->base + ONENAND_REG_START_ADDRESS1);
+
+ /* Check lock status */
+ status = this->read_word(this->base + ONENAND_REG_WP_STATUS);
+ if (!(status & ONENAND_WP_US))
+ printk(KERN_ERR "block = %d, wp status = 0x%x\n",
+ block, status);
+ }
+
+ return 0;
+}
+
+/**
+ * onenand_print_device_info - Print device ID
+ * @param device device ID
+ *
+ * Print device ID
+ */
+void onenand_print_device_info(int device, int verbose)
+{
+ int vcc, demuxed, ddp, density;
+
+ if (!verbose)
+ return;
+
+ vcc = device & ONENAND_DEVICE_VCC_MASK;
+ demuxed = device & ONENAND_DEVICE_IS_DEMUX;
+ ddp = device & ONENAND_DEVICE_IS_DDP;
+ density = device >> ONENAND_DEVICE_DENSITY_SHIFT;
+ printk(KERN_INFO "%sOneNAND%s %dMB %sV 16-bit (0x%02x)\n",
+ demuxed ? "" : "Muxed ",
+ ddp ? "(DDP)" : "",
+ (16 << density), vcc ? "2.65/3.3" : "1.8", device);
+}
+
+static const struct onenand_manufacturers onenand_manuf_ids[] = {
+ {ONENAND_MFR_SAMSUNG, "Samsung"},
+ {ONENAND_MFR_UNKNOWN, "Unknown"}
+};
+
+/**
+ * onenand_check_maf - Check manufacturer ID
+ * @param manuf manufacturer ID
+ *
+ * Check manufacturer ID
+ */
+static int onenand_check_maf(int manuf)
+{
+ int i;
+
+ for (i = 0; onenand_manuf_ids[i].id; i++) {
+ if (manuf == onenand_manuf_ids[i].id)
+ break;
+ }
+
+#ifdef ONENAND_DEBUG
+ printk(KERN_DEBUG "OneNAND Manufacturer: %s (0x%0x)\n",
+ onenand_manuf_ids[i].name, manuf);
+#endif
+
+ return (i != ONENAND_MFR_UNKNOWN);
+}
+
+/**
+ * onenand_probe - [OneNAND Interface] Probe the OneNAND device
+ * @param mtd MTD device structure
+ *
+ * OneNAND detection method:
+ * Compare the the values from command with ones from register
+ */
+static int onenand_probe(struct mtd_info *mtd)
+{
+ struct onenand_chip *this = mtd->priv;
+ int bram_maf_id, bram_dev_id, maf_id, dev_id;
+ int version_id;
+ int density;
+
+ /* Send the command for reading device ID from BootRAM */
+ this->write_word(ONENAND_CMD_READID, this->base + ONENAND_BOOTRAM);
+
+ /* Read manufacturer and device IDs from BootRAM */
+ bram_maf_id = this->read_word(this->base + ONENAND_BOOTRAM + 0x0);
+ bram_dev_id = this->read_word(this->base + ONENAND_BOOTRAM + 0x2);
+
+ /* Check manufacturer ID */
+ if (onenand_check_maf(bram_maf_id))
+ return -ENXIO;
+
+ /* Reset OneNAND to read default register values */
+ this->write_word(ONENAND_CMD_RESET, this->base + ONENAND_BOOTRAM);
+
+ {
+ int i;
+ for (i = 0; i < 10000; i++) ;
+ }
+
+ /* Read manufacturer and device IDs from Register */
+ maf_id = this->read_word(this->base + ONENAND_REG_MANUFACTURER_ID);
+ dev_id = this->read_word(this->base + ONENAND_REG_DEVICE_ID);
+
+ /* Check OneNAND device */
+ if (maf_id != bram_maf_id || dev_id != bram_dev_id)
+ return -ENXIO;
+
+ /* Flash device information */
+ onenand_print_device_info(dev_id, 0);
+ this->device_id = dev_id;
+
+ density = dev_id >> ONENAND_DEVICE_DENSITY_SHIFT;
+ this->chipsize = (16 << density) << 20;
+
+ /* OneNAND page size & block size */
+ /* The data buffer size is equal to page size */
+ mtd->oobblock =
+ this->read_word(this->base + ONENAND_REG_DATA_BUFFER_SIZE);
+ mtd->oobsize = mtd->oobblock >> 5;
+ /* Pagers per block is always 64 in OneNAND */
+ mtd->erasesize = mtd->oobblock << 6;
+
+ this->erase_shift = ffs(mtd->erasesize) - 1;
+ this->page_shift = ffs(mtd->oobblock) - 1;
+ this->ppb_shift = (this->erase_shift - this->page_shift);
+ this->page_mask = (mtd->erasesize / mtd->oobblock) - 1;
+
+ /* REVIST: Multichip handling */
+
+ mtd->size = this->chipsize;
+
+ /* Version ID */
+ version_id = this->read_word(this->base + ONENAND_REG_VERSION_ID);
+#ifdef ONENAND_DEBUG
+ printk(KERN_DEBUG "OneNAND version = 0x%04x\n", version_id);
+#endif
+
+ /* Lock scheme */
+ if (density <= ONENAND_DEVICE_DENSITY_512Mb &&
+ !(version_id >> ONENAND_VERSION_PROCESS_SHIFT)) {
+ printk(KERN_INFO "Lock scheme is Continues Lock\n");
+ this->options |= ONENAND_CONT_LOCK;
+ }
+
+ return 0;
+}
+
+/**
+ * onenand_scan - [OneNAND Interface] Scan for the OneNAND device
+ * @param mtd MTD device structure
+ * @param maxchips Number of chips to scan for
+ *
+ * This fills out all the not initialized function pointers
+ * with the defaults.
+ * The flash ID is read and the mtd/chip structures are
+ * filled with the appropriate values.
+ */
+int onenand_scan(struct mtd_info *mtd, int maxchips)
+{
+ struct onenand_chip *this = mtd->priv;
+
+ if (!this->read_word)
+ this->read_word = onenand_readw;
+ if (!this->write_word)
+ this->write_word = onenand_writew;
+
+ if (!this->command)
+ this->command = onenand_command;
+ if (!this->wait)
+ this->wait = onenand_wait;
+
+ if (!this->read_bufferram)
+ this->read_bufferram = onenand_read_bufferram;
+ if (!this->write_bufferram)
+ this->write_bufferram = onenand_write_bufferram;
+
+ if (onenand_probe(mtd))
+ return -ENXIO;
+
+ /* Set Sync. Burst Read after probing */
+ if (this->mmcontrol) {
+ printk(KERN_INFO "OneNAND Sync. Burst Read support\n");
+ this->read_bufferram = onenand_sync_read_bufferram;
+ }
+
+ onenand_unlock(mtd, 0, mtd->size);
+
+ return onenand_default_bbt(mtd);
+}
+
+/**
+ * onenand_release - [OneNAND Interface] Free resources held by the OneNAND device
+ * @param mtd MTD device structure
+ */
+void onenand_release(struct mtd_info *mtd)
+{
+}
+
+/*
+ * OneNAND initialization at U-Boot
+ */
+struct mtd_info onenand_mtd;
+struct onenand_chip onenand_chip;
+
+void onenand_init(void)
+{
+ memset(&onenand_mtd, 0, sizeof(struct mtd_info));
+ memset(&onenand_chip, 0, sizeof(struct onenand_chip));
+
+ onenand_chip.base = (void *)CFG_ONENAND_BASE;
+ onenand_mtd.priv = &onenand_chip;
+
+ onenand_scan(&onenand_mtd, 1);
+
+ puts("OneNAND: ");
+ print_size(onenand_mtd.size, "\n");
+}
+
+#endif /* CONFIG_CMD_ONENAND */
diff --git a/drivers/onenand/onenand_bbt.c b/drivers/onenand/onenand_bbt.c
new file mode 100644
index 0000000000..5a610ee5ea
--- /dev/null
+++ b/drivers/onenand/onenand_bbt.c
@@ -0,0 +1,265 @@
+/*
+ * linux/drivers/mtd/onenand/onenand_bbt.c
+ *
+ * Bad Block Table support for the OneNAND driver
+ *
+ * Copyright(c) 2005-2007 Samsung Electronics
+ * Kyungmin Park <kyungmin.park@samsung.com>
+ *
+ * TODO:
+ * Split BBT core and chip specific BBT.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <common.h>
+
+#ifdef CONFIG_CMD_ONENAND
+
+#include <linux/mtd/compat.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/onenand.h>
+#include <malloc.h>
+
+#include <asm/errno.h>
+
+/**
+ * check_short_pattern - [GENERIC] check if a pattern is in the buffer
+ * @param buf the buffer to search
+ * @param len the length of buffer to search
+ * @param paglen the pagelength
+ * @param td search pattern descriptor
+ *
+ * Check for a pattern at the given place. Used to search bad block
+ * tables and good / bad block identifiers. Same as check_pattern, but
+ * no optional empty check and the pattern is expected to start
+ * at offset 0.
+ */
+static int check_short_pattern(uint8_t * buf, int len, int paglen,
+ struct nand_bbt_descr *td)
+{
+ int i;
+ uint8_t *p = buf;
+
+ /* Compare the pattern */
+ for (i = 0; i < td->len; i++) {
+ if (p[i] != td->pattern[i])
+ return -1;
+ }
+ return 0;
+}
+
+/**
+ * create_bbt - [GENERIC] Create a bad block table by scanning the device
+ * @param mtd MTD device structure
+ * @param buf temporary buffer
+ * @param bd descriptor for the good/bad block search pattern
+ * @param chip create the table for a specific chip, -1 read all chips.
+ * Applies only if NAND_BBT_PERCHIP option is set
+ *
+ * Create a bad block table by scanning the device
+ * for the given good/bad block identify pattern
+ */
+static int create_bbt(struct mtd_info *mtd, uint8_t * buf,
+ struct nand_bbt_descr *bd, int chip)
+{
+ struct onenand_chip *this = mtd->priv;
+ struct bbm_info *bbm = this->bbm;
+ int i, j, numblocks, len, scanlen;
+ int startblock;
+ loff_t from;
+ size_t readlen, ooblen;
+
+ printk(KERN_INFO "Scanning device for bad blocks\n");
+
+ len = 1;
+
+ /* We need only read few bytes from the OOB area */
+ scanlen = ooblen = 0;
+ readlen = bd->len;
+
+ /* chip == -1 case only */
+ /* Note that numblocks is 2 * (real numblocks) here;
+ * see i += 2 below as it makses shifting and masking less painful
+ */
+ numblocks = mtd->size >> (bbm->bbt_erase_shift - 1);
+ startblock = 0;
+ from = 0;
+
+ for (i = startblock; i < numblocks;) {
+ int ret;
+
+ for (j = 0; j < len; j++) {
+ size_t retlen;
+
+ /* No need to read pages fully,
+ * just read required OOB bytes */
+ ret = onenand_read_oob(mtd,
+ from + j * mtd->oobblock +
+ bd->offs, readlen, &retlen,
+ &buf[0]);
+
+ if (ret && ret != -EAGAIN) {
+ printk("ret = %d\n", ret);
+ return ret;
+ }
+
+ if (check_short_pattern
+ (&buf[j * scanlen], scanlen, mtd->oobblock, bd)) {
+ bbm->bbt[i >> 3] |= 0x03 << (i & 0x6);
+ printk(KERN_WARNING
+ "Bad eraseblock %d at 0x%08x\n", i >> 1,
+ (unsigned int)from);
+ break;
+ }
+ }
+ i += 2;
+ from += (1 << bbm->bbt_erase_shift);
+ }
+
+ return 0;
+}
+
+/**
+ * onenand_memory_bbt - [GENERIC] create a memory based bad block table
+ * @param mtd MTD device structure
+ * @param bd descriptor for the good/bad block search pattern
+ *
+ * The function creates a memory based bbt by scanning the device
+ * for manufacturer / software marked good / bad blocks
+ */
+static inline int onenand_memory_bbt(struct mtd_info *mtd,
+ struct nand_bbt_descr *bd)
+{
+ unsigned char data_buf[MAX_ONENAND_PAGESIZE];
+
+ bd->options &= ~NAND_BBT_SCANEMPTY;
+ return create_bbt(mtd, data_buf, bd, -1);
+}
+
+/**
+ * onenand_isbad_bbt - [OneNAND Interface] Check if a block is bad
+ * @param mtd MTD device structure
+ * @param offs offset in the device
+ * @param allowbbt allow access to bad block table region
+ */
+static int onenand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt)
+{
+ struct onenand_chip *this = mtd->priv;
+ struct bbm_info *bbm = this->bbm;
+ int block;
+ uint8_t res;
+
+ /* Get block number * 2 */
+ block = (int)(offs >> (bbm->bbt_erase_shift - 1));
+ res = (bbm->bbt[block >> 3] >> (block & 0x06)) & 0x03;
+
+ DEBUG(MTD_DEBUG_LEVEL2,
+ "onenand_isbad_bbt: bbt info for offs 0x%08x: (block %d) 0x%02x\n",
+ (unsigned int)offs, block >> 1, res);
+
+ switch ((int)res) {
+ case 0x00:
+ return 0;
+ case 0x01:
+ return 1;
+ case 0x02:
+ return allowbbt ? 0 : 1;
+ }
+
+ return 1;
+}
+
+/**
+ * onenand_scan_bbt - [OneNAND Interface] scan, find, read and maybe create bad block table(s)
+ * @param mtd MTD device structure
+ * @param bd descriptor for the good/bad block search pattern
+ *
+ * The function checks, if a bad block table(s) is/are already
+ * available. If not it scans the device for manufacturer
+ * marked good / bad blocks and writes the bad block table(s) to
+ * the selected place.
+ *
+ * The bad block table memory is allocated here. It must be freed
+ * by calling the onenand_free_bbt function.
+ *
+ */
+int onenand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
+{
+ struct onenand_chip *this = mtd->priv;
+ struct bbm_info *bbm = this->bbm;
+ int len, ret = 0;
+
+ len = mtd->size >> (this->erase_shift + 2);
+ /* Allocate memory (2bit per block) */
+ bbm->bbt = malloc(len);
+ if (!bbm->bbt) {
+ printk(KERN_ERR "onenand_scan_bbt: Out of memory\n");
+ return -ENOMEM;
+ }
+ /* Clear the memory bad block table */
+ memset(bbm->bbt, 0x00, len);
+
+ /* Set the bad block position */
+ bbm->badblockpos = ONENAND_BADBLOCK_POS;
+
+ /* Set erase shift */
+ bbm->bbt_erase_shift = this->erase_shift;
+
+ if (!bbm->isbad_bbt)
+ bbm->isbad_bbt = onenand_isbad_bbt;
+
+ /* Scan the device to build a memory based bad block table */
+ if ((ret = onenand_memory_bbt(mtd, bd))) {
+ printk(KERN_ERR
+ "onenand_scan_bbt: Can't scan flash and build the RAM-based BBT\n");
+ free(bbm->bbt);
+ bbm->bbt = NULL;
+ }
+
+ return ret;
+}
+
+/*
+ * Define some generic bad / good block scan pattern which are used
+ * while scanning a device for factory marked good / bad blocks.
+ */
+static uint8_t scan_ff_pattern[] = { 0xff, 0xff };
+
+static struct nand_bbt_descr largepage_memorybased = {
+ .options = 0,
+ .offs = 0,
+ .len = 2,
+ .pattern = scan_ff_pattern,
+};
+
+/**
+ * onenand_default_bbt - [OneNAND Interface] Select a default bad block table for the device
+ * @param mtd MTD device structure
+ *
+ * This function selects the default bad block table
+ * support for the device and calls the onenand_scan_bbt function
+ */
+int onenand_default_bbt(struct mtd_info *mtd)
+{
+ struct onenand_chip *this = mtd->priv;
+ struct bbm_info *bbm;
+
+ this->bbm = malloc(sizeof(struct bbm_info));
+ if (!this->bbm)
+ return -ENOMEM;
+
+ bbm = this->bbm;
+
+ memset(bbm, 0, sizeof(struct bbm_info));
+
+ /* 1KB page has same configuration as 2KB page */
+ if (!bbm->badblock_pattern)
+ bbm->badblock_pattern = &largepage_memorybased;
+
+ return onenand_scan_bbt(mtd, bbm->badblock_pattern);
+}
+
+#endif /* CFG_CMD_ONENAND */
diff --git a/drivers/s3c4510b_eth.c b/drivers/s3c4510b_eth.c
index 48901aa12f..3d9066abea 100644
--- a/drivers/s3c4510b_eth.c
+++ b/drivers/s3c4510b_eth.c
@@ -175,7 +175,7 @@ s32 eth_send(volatile void *packet, s32 length)
}
/* copy user data into frame data pointer */
- memcpy((void *)(eth->m_curTX_FD->m_frameDataPtr.bf.dataPtr),
+ memcpy((void *)((u32)(eth->m_curTX_FD->m_frameDataPtr.bf.dataPtr)),
(void *)packet,
length);
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index 93c68dd2e0..40f3d672ec 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -25,7 +25,7 @@ include $(TOPDIR)/config.mk
LIB := $(obj)libserial.a
-COBJS := mcfuart.o
+COBJS := mcfuart.o serial_pl010.o serial_pl011.o
SRCS := $(COBJS:.o=.c)
OBJS := $(addprefix $(obj),$(COBJS))
diff --git a/drivers/serial_pl010.c b/drivers/serial/serial_pl010.c
index 417b6aeda6..417b6aeda6 100644
--- a/drivers/serial_pl010.c
+++ b/drivers/serial/serial_pl010.c
diff --git a/drivers/serial_pl011.c b/drivers/serial/serial_pl011.c
index 4d35fe5e9e..4d35fe5e9e 100644
--- a/drivers/serial_pl011.c
+++ b/drivers/serial/serial_pl011.c
diff --git a/drivers/serial_pl011.h b/drivers/serial/serial_pl011.h
index 5f20fdd108..5f20fdd108 100644
--- a/drivers/serial_pl011.h
+++ b/drivers/serial/serial_pl011.h
diff --git a/drivers/serial_xuartlite.c b/drivers/serial_xuartlite.c
index ed59abea86..d678ab6b76 100644
--- a/drivers/serial_xuartlite.c
+++ b/drivers/serial_xuartlite.c
@@ -24,7 +24,7 @@
#include <config.h>
-#ifdef CONFIG_MICROBLAZE
+#ifdef CONFIG_XILINX_UARTLITE
#include <asm/serial_xuartlite.h>
diff --git a/drivers/sk98lin/Makefile b/drivers/sk98lin/Makefile
index 7e50b1df98..a7d4a3b7a7 100644
--- a/drivers/sk98lin/Makefile
+++ b/drivers/sk98lin/Makefile
@@ -29,12 +29,26 @@ include $(TOPDIR)/config.mk
LIB := $(obj)libsk98lin.a
-COBJS := skge.o skaddr.o skgehwt.o skgeinit.o skgepnmi.o skgesirq.o \
- ski2c.o sklm80.o skqueue.o skrlmt.o sktimer.o skvpd.o \
- skxmac2.o skcsum.o #skproc.o
-
-COBJS += uboot_skb.o uboot_drv.o
-
+COBJS-y += skge.o
+COBJS-y += skaddr.o
+COBJS-y += skgehwt.o
+COBJS-y += skgeinit.o
+COBJS-y += skgepnmi.o
+COBJS-y += skgesirq.o
+COBJS-y += ski2c.o
+COBJS-y += sklm80.o
+COBJS-y += skqueue.o
+COBJS-y += skrlmt.o
+COBJS-y += sktimer.o
+COBJS-y += skvpd.o
+COBJS-y += skxmac2.o
+COBJS-y += skcsum.o
+#COBJS-y += skproc.o
+
+COBJS-y += uboot_skb.o
+COBJS-y += uboot_drv.o
+
+COBJS := $(COBJS-y)
SRCS := $(COBJS:.o=.c)
OBJS := $(addprefix $(obj),$(COBJS))
diff --git a/drivers/tsec.c b/drivers/tsec.c
index 4ff3339c7d..ca6284b726 100644
--- a/drivers/tsec.c
+++ b/drivers/tsec.c
@@ -117,10 +117,13 @@ 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);
+#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) \
+ && !defined(BITBANGMII)
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);
+#endif
#ifdef CONFIG_MCAST_TFTP
static int tsec_mcast_addr (struct eth_device *dev, u8 mcast_mac, u8 set);
#endif
@@ -803,6 +806,7 @@ static void startup_tsec(struct eth_device *dev)
/* Tell the DMA it is clear to go */
regs->dmactrl |= DMACTRL_INIT_SETTINGS;
regs->tstat = TSTAT_CLEAR_THALT;
+ regs->rstat = RSTAT_CLEAR_RHALT;
regs->dmactrl &= ~(DMACTRL_GRS | DMACTRL_GTS);
}
diff --git a/drivers/tsi108_i2c.c b/drivers/tsi108_i2c.c
index 3a3b75c39b..d6736b0477 100644
--- a/drivers/tsi108_i2c.c
+++ b/drivers/tsi108_i2c.c
@@ -276,7 +276,7 @@ int i2c_probe (uchar chip)
* The Tsi108 HW doesn't support sending just the chip address
* and checkong for an <ACK> back.
*/
- return i2c_read (chip, 0, 1, (char *)&tmp, 1);
+ return i2c_read (chip, 0, 1, (uchar *)&tmp, 1);
}
#endif
diff --git a/drivers/tsi108_pci.c b/drivers/tsi108_pci.c
index 9f606df518..d5f11e42f0 100644
--- a/drivers/tsi108_pci.c
+++ b/drivers/tsi108_pci.c
@@ -33,6 +33,9 @@
#include <pci.h>
#include <asm/io.h>
#include <tsi108.h>
+#ifdef CONFIG_OF_FLAT_TREE
+#include <ft_build.h>
+#endif
struct pci_controller local_hose;
diff --git a/drivers/uli526x.c b/drivers/uli526x.c
new file mode 100644
index 0000000000..1267c5798f
--- /dev/null
+++ b/drivers/uli526x.c
@@ -0,0 +1,996 @@
+/*
+ * Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ * Author: Roy Zang <tie-fei.zang@freescale.com>, Sep, 2007
+ *
+ * Description:
+ * ULI 526x Ethernet port driver.
+ * Based on the Linux driver: drivers/net/tulip/uli526x.c
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <net.h>
+#include <asm/io.h>
+#include <pci.h>
+#include <miiphy.h>
+
+/* some kernel function compatible define */
+
+#if defined(CONFIG_CMD_NET) && defined(CONFIG_NET_MULTI) && \
+ defined(CONFIG_ULI526X)
+
+#undef DEBUG
+
+/* Board/System/Debug information/definition */
+#define ULI_VENDOR_ID 0x10B9
+#define ULI5261_DEVICE_ID 0x5261
+#define ULI5263_DEVICE_ID 0x5263
+/* ULi M5261 ID*/
+#define PCI_ULI5261_ID ULI5261_DEVICE_ID << 16 | ULI_VENDOR_ID
+/* ULi M5263 ID*/
+#define PCI_ULI5263_ID ULI5263_DEVICE_ID << 16 | ULI_VENDOR_ID
+
+#define ULI526X_IO_SIZE 0x100
+#define TX_DESC_CNT 0x10 /* Allocated Tx descriptors */
+#define RX_DESC_CNT PKTBUFSRX /* Allocated Rx descriptors */
+#define TX_FREE_DESC_CNT (TX_DESC_CNT - 2) /* Max TX packet count */
+#define TX_WAKE_DESC_CNT (TX_DESC_CNT - 3) /* TX wakeup count */
+#define DESC_ALL_CNT (TX_DESC_CNT + RX_DESC_CNT)
+#define TX_BUF_ALLOC 0x300
+#define RX_ALLOC_SIZE PKTSIZE
+#define ULI526X_RESET 1
+#define CR0_DEFAULT 0
+#define CR6_DEFAULT 0x22200000
+#define CR7_DEFAULT 0x180c1
+#define CR15_DEFAULT 0x06 /* TxJabber RxWatchdog */
+#define TDES0_ERR_MASK 0x4302 /* TXJT, LC, EC, FUE */
+#define MAX_PACKET_SIZE 1514
+#define ULI5261_MAX_MULTICAST 14
+#define RX_COPY_SIZE 100
+#define MAX_CHECK_PACKET 0x8000
+
+#define ULI526X_10MHF 0
+#define ULI526X_100MHF 1
+#define ULI526X_10MFD 4
+#define ULI526X_100MFD 5
+#define ULI526X_AUTO 8
+
+#define ULI526X_TXTH_72 0x400000 /* TX TH 72 byte */
+#define ULI526X_TXTH_96 0x404000 /* TX TH 96 byte */
+#define ULI526X_TXTH_128 0x0000 /* TX TH 128 byte */
+#define ULI526X_TXTH_256 0x4000 /* TX TH 256 byte */
+#define ULI526X_TXTH_512 0x8000 /* TX TH 512 byte */
+#define ULI526X_TXTH_1K 0xC000 /* TX TH 1K byte */
+
+/* CR9 definition: SROM/MII */
+#define CR9_SROM_READ 0x4800
+#define CR9_SRCS 0x1
+#define CR9_SRCLK 0x2
+#define CR9_CRDOUT 0x8
+#define SROM_DATA_0 0x0
+#define SROM_DATA_1 0x4
+#define PHY_DATA_1 0x20000
+#define PHY_DATA_0 0x00000
+#define MDCLKH 0x10000
+
+#define PHY_POWER_DOWN 0x800
+
+#define SROM_V41_CODE 0x14
+
+#define SROM_CLK_WRITE(data, ioaddr) do { \
+ outl(data|CR9_SROM_READ|CR9_SRCS, ioaddr); \
+ udelay(5); \
+ outl(data|CR9_SROM_READ|CR9_SRCS|CR9_SRCLK, ioaddr); \
+ udelay(5); \
+ outl(data|CR9_SROM_READ|CR9_SRCS, ioaddr); \
+ udelay(5); \
+ } while (0)
+
+/* Structure/enum declaration */
+
+struct tx_desc {
+ u32 tdes0, tdes1, tdes2, tdes3; /* Data for the card */
+ char *tx_buf_ptr; /* Data for us */
+ struct tx_desc *next_tx_desc;
+};
+
+struct rx_desc {
+ u32 rdes0, rdes1, rdes2, rdes3; /* Data for the card */
+ char *rx_buf_ptr; /* Data for us */
+ struct rx_desc *next_rx_desc;
+};
+
+struct uli526x_board_info {
+ u32 chip_id; /* Chip vendor/Device ID */
+ pci_dev_t pdev;
+
+ long ioaddr; /* I/O base address */
+ u32 cr0_data;
+ u32 cr5_data;
+ u32 cr6_data;
+ u32 cr7_data;
+ u32 cr15_data;
+
+ /* pointer for memory physical address */
+ dma_addr_t buf_pool_dma_ptr; /* Tx buffer pool memory */
+ dma_addr_t buf_pool_dma_start; /* Tx buffer pool align dword */
+ dma_addr_t desc_pool_dma_ptr; /* descriptor pool memory */
+ dma_addr_t first_tx_desc_dma;
+ dma_addr_t first_rx_desc_dma;
+
+ /* descriptor pointer */
+ unsigned char *buf_pool_ptr; /* Tx buffer pool memory */
+ unsigned char *buf_pool_start; /* Tx buffer pool align dword */
+ unsigned char *desc_pool_ptr; /* descriptor pool memory */
+ struct tx_desc *first_tx_desc;
+ struct tx_desc *tx_insert_ptr;
+ struct tx_desc *tx_remove_ptr;
+ struct rx_desc *first_rx_desc;
+ struct rx_desc *rx_ready_ptr; /* packet come pointer */
+ unsigned long tx_packet_cnt; /* transmitted packet count */
+
+ u16 PHY_reg4; /* Saved Phyxcer register 4 value */
+
+ u8 media_mode; /* user specify media mode */
+ u8 op_mode; /* real work dedia mode */
+ u8 phy_addr;
+
+ /* NIC SROM data */
+ unsigned char srom[128];
+};
+
+enum uli526x_offsets {
+ DCR0 = 0x00, DCR1 = 0x08, DCR2 = 0x10, DCR3 = 0x18, DCR4 = 0x20,
+ DCR5 = 0x28, DCR6 = 0x30, DCR7 = 0x38, DCR8 = 0x40, DCR9 = 0x48,
+ DCR10 = 0x50, DCR11 = 0x58, DCR12 = 0x60, DCR13 = 0x68, DCR14 = 0x70,
+ DCR15 = 0x78
+};
+
+enum uli526x_CR6_bits {
+ CR6_RXSC = 0x2, CR6_PBF = 0x8, CR6_PM = 0x40, CR6_PAM = 0x80,
+ CR6_FDM = 0x200, CR6_TXSC = 0x2000, CR6_STI = 0x100000,
+ CR6_SFT = 0x200000, CR6_RXA = 0x40000000, CR6_NO_PURGE = 0x20000000
+};
+
+/* Global variable declaration -- */
+
+static unsigned char uli526x_media_mode = ULI526X_AUTO;
+
+static struct tx_desc desc_pool_array[DESC_ALL_CNT + 0x20]
+ __attribute__ ((aligned(32)));
+static char buf_pool[TX_BUF_ALLOC * TX_DESC_CNT + 4];
+
+/* For module input parameter */
+static int mode = 8;
+
+/* function declaration -- */
+static int uli526x_start_xmit(struct eth_device *dev,
+ volatile void *packet, int length);
+static const struct ethtool_ops netdev_ethtool_ops;
+static u16 read_srom_word(long, int);
+static void uli526x_descriptor_init(struct uli526x_board_info *, unsigned long);
+static void allocate_rx_buffer(struct uli526x_board_info *);
+static void update_cr6(u32, unsigned long);
+static u16 phy_read(unsigned long, u8, u8, u32);
+static u16 phy_readby_cr10(unsigned long, u8, u8);
+static void phy_write(unsigned long, u8, u8, u16, u32);
+static void phy_writeby_cr10(unsigned long, u8, u8, u16);
+static void phy_write_1bit(unsigned long, u32, u32);
+static u16 phy_read_1bit(unsigned long, u32);
+static int uli526x_rx_packet(struct eth_device *);
+static void uli526x_free_tx_pkt(struct eth_device *,
+ struct uli526x_board_info *);
+static void uli526x_reuse_buf(struct rx_desc *);
+static void uli526x_init(struct eth_device *);
+static void uli526x_set_phyxcer(struct uli526x_board_info *);
+
+
+static int uli526x_init_one(struct eth_device *, bd_t *);
+static void uli526x_disable(struct eth_device *);
+static void set_mac_addr(struct eth_device *);
+
+static struct pci_device_id uli526x_pci_tbl[] = {
+ { ULI_VENDOR_ID, ULI5261_DEVICE_ID}, /* 5261 device */
+ { ULI_VENDOR_ID, ULI5263_DEVICE_ID}, /* 5263 device */
+ {}
+};
+
+/* ULI526X network board routine */
+
+/*
+ * Search ULI526X board, register it
+ */
+
+int uli526x_initialize(bd_t *bis)
+{
+ pci_dev_t devno;
+ int card_number = 0;
+ struct eth_device *dev;
+ struct uli526x_board_info *db; /* board information structure */
+
+ u32 iobase;
+ int idx = 0;
+
+ while (1) {
+ /* Find PCI device */
+ devno = pci_find_devices(uli526x_pci_tbl, idx++);
+ if (devno < 0)
+ break;
+
+ pci_read_config_dword(devno, PCI_BASE_ADDRESS_1, &iobase);
+ iobase &= ~0xf;
+
+ dev = (struct eth_device *)malloc(sizeof *dev);
+ sprintf(dev->name, "uli526x#%d\n", card_number);
+ db = (struct uli526x_board_info *)
+ malloc(sizeof(struct uli526x_board_info));
+
+ dev->priv = db;
+ db->pdev = devno;
+ dev->iobase = iobase;
+
+ dev->init = uli526x_init_one;
+ dev->halt = uli526x_disable;
+ dev->send = uli526x_start_xmit;
+ dev->recv = uli526x_rx_packet;
+
+ /* init db */
+ db->ioaddr = dev->iobase;
+ /* get chip id */
+
+ pci_read_config_dword(devno, PCI_VENDOR_ID, &db->chip_id);
+#ifdef DEBUG
+ printf("uli526x: uli526x @0x%x\n", iobase);
+ printf("uli526x: chip_id%x\n", db->chip_id);
+#endif
+ eth_register(dev);
+ card_number++;
+ pci_write_config_byte(devno, PCI_LATENCY_TIMER, 0x20);
+ udelay(10 * 1000);
+ }
+ return card_number;
+}
+
+static int uli526x_init_one(struct eth_device *dev, bd_t *bis)
+{
+
+ struct uli526x_board_info *db = dev->priv;
+ int i;
+
+ switch (mode) {
+ case ULI526X_10MHF:
+ case ULI526X_100MHF:
+ case ULI526X_10MFD:
+ case ULI526X_100MFD:
+ uli526x_media_mode = mode;
+ break;
+ default:
+ uli526x_media_mode = ULI526X_AUTO;
+ break;
+ }
+
+ /* Allocate Tx/Rx descriptor memory */
+ db->desc_pool_ptr = (uchar *)&desc_pool_array[0];
+ db->desc_pool_dma_ptr = (dma_addr_t)&desc_pool_array[0];
+ if (db->desc_pool_ptr == NULL)
+ return 0;
+
+ db->buf_pool_ptr = &buf_pool[0];
+ db->buf_pool_dma_ptr = (dma_addr_t)&buf_pool[0];
+ if (db->buf_pool_ptr == NULL)
+ return 0;
+
+ db->first_tx_desc = (struct tx_desc *) db->desc_pool_ptr;
+ db->first_tx_desc_dma = db->desc_pool_dma_ptr;
+
+ db->buf_pool_start = db->buf_pool_ptr;
+ db->buf_pool_dma_start = db->buf_pool_dma_ptr;
+
+#ifdef DEBUG
+ printf("%s(): db->ioaddr= 0x%x\n",
+ __FUNCTION__, db->ioaddr);
+ printf("%s(): media_mode= 0x%x\n",
+ __FUNCTION__, uli526x_media_mode);
+ printf("%s(): db->desc_pool_ptr= 0x%x\n",
+ __FUNCTION__, db->desc_pool_ptr);
+ printf("%s(): db->desc_pool_dma_ptr= 0x%x\n",
+ __FUNCTION__, db->desc_pool_dma_ptr);
+ printf("%s(): db->buf_pool_ptr= 0x%x\n",
+ __FUNCTION__, db->buf_pool_ptr);
+ printf("%s(): db->buf_pool_dma_ptr= 0x%x\n",
+ __FUNCTION__, db->buf_pool_dma_ptr);
+#endif
+
+ /* read 64 word srom data */
+ for (i = 0; i < 64; i++)
+ ((u16 *) db->srom)[i] = cpu_to_le16(read_srom_word(db->ioaddr,
+ i));
+
+ /* Set Node address */
+ if (((u16 *) db->srom)[0] == 0xffff || ((u16 *) db->srom)[0] == 0)
+ /* SROM absent, so write MAC address to ID Table */
+ set_mac_addr(dev);
+ else { /*Exist SROM*/
+ for (i = 0; i < 6; i++)
+ dev->enetaddr[i] = db->srom[20 + i];
+ }
+#ifdef DEBUG
+ for (i = 0; i < 6; i++)
+ printf("%c%02x", i ? ':' : ' ', dev->enetaddr[i]);
+#endif
+ db->PHY_reg4 = 0x1e0;
+
+ /* system variable init */
+ db->cr6_data = CR6_DEFAULT ;
+ db->cr6_data |= ULI526X_TXTH_256;
+ db->cr0_data = CR0_DEFAULT;
+ uli526x_init(dev);
+ return 1;
+}
+
+static void uli526x_disable(struct eth_device *dev)
+{
+#ifdef DEBUG
+ printf("uli526x_disable\n");
+#endif
+ struct uli526x_board_info *db = dev->priv;
+
+ if (!((inl(db->ioaddr + DCR12)) & 0x8)) {
+ /* Reset & stop ULI526X board */
+ outl(ULI526X_RESET, db->ioaddr + DCR0);
+ udelay(5);
+ phy_write(db->ioaddr, db->phy_addr, 0, 0x8000, db->chip_id);
+
+ /* reset the board */
+ db->cr6_data &= ~(CR6_RXSC | CR6_TXSC); /* Disable Tx/Rx */
+ update_cr6(db->cr6_data, dev->iobase);
+ outl(0, dev->iobase + DCR7); /* Disable Interrupt */
+ outl(inl(dev->iobase + DCR5), dev->iobase + DCR5);
+ }
+}
+
+/* Initialize ULI526X board
+ * Reset ULI526X board
+ * Initialize TX/Rx descriptor chain structure
+ * Send the set-up frame
+ * Enable Tx/Rx machine
+ */
+
+static void uli526x_init(struct eth_device *dev)
+{
+
+ struct uli526x_board_info *db = dev->priv;
+ u8 phy_tmp;
+ u16 phy_value;
+ u16 phy_reg_reset;
+
+ /* Reset M526x MAC controller */
+ outl(ULI526X_RESET, db->ioaddr + DCR0); /* RESET MAC */
+ udelay(100);
+ outl(db->cr0_data, db->ioaddr + DCR0);
+ udelay(5);
+
+ /* Phy addr : In some boards,M5261/M5263 phy address != 1 */
+ db->phy_addr = 1;
+ db->tx_packet_cnt = 0;
+ for (phy_tmp = 0; phy_tmp < 32; phy_tmp++) {
+ /* peer add */
+ phy_value = phy_read(db->ioaddr, phy_tmp, 3, db->chip_id);
+ if (phy_value != 0xffff && phy_value != 0) {
+ db->phy_addr = phy_tmp;
+ break;
+ }
+ }
+
+#ifdef DEBUG
+ printf("%s(): db->ioaddr= 0x%x\n", __FUNCTION__, db->ioaddr);
+ printf("%s(): db->phy_addr= 0x%x\n", __FUNCTION__, db->phy_addr);
+#endif
+ if (phy_tmp == 32)
+ printf("Can not find the phy address!!!");
+
+ /* Parser SROM and media mode */
+ db->media_mode = uli526x_media_mode;
+
+ if (!(inl(db->ioaddr + DCR12) & 0x8)) {
+ /* Phyxcer capability setting */
+ phy_reg_reset = phy_read(db->ioaddr,
+ db->phy_addr, 0, db->chip_id);
+ phy_reg_reset = (phy_reg_reset | 0x8000);
+ phy_write(db->ioaddr, db->phy_addr, 0,
+ phy_reg_reset, db->chip_id);
+ udelay(500);
+
+ /* Process Phyxcer Media Mode */
+ uli526x_set_phyxcer(db);
+ }
+ /* Media Mode Process */
+ if (!(db->media_mode & ULI526X_AUTO))
+ db->op_mode = db->media_mode; /* Force Mode */
+
+ /* Initialize Transmit/Receive decriptor and CR3/4 */
+ uli526x_descriptor_init(db, db->ioaddr);
+
+ /* Init CR6 to program M526X operation */
+ update_cr6(db->cr6_data, db->ioaddr);
+
+ /* Init CR7, interrupt active bit */
+ db->cr7_data = CR7_DEFAULT;
+ outl(db->cr7_data, db->ioaddr + DCR7);
+
+ /* Init CR15, Tx jabber and Rx watchdog timer */
+ outl(db->cr15_data, db->ioaddr + DCR15);
+
+ /* Enable ULI526X Tx/Rx function */
+ db->cr6_data |= CR6_RXSC | CR6_TXSC;
+ update_cr6(db->cr6_data, db->ioaddr);
+ while (!(inl(db->ioaddr + DCR12) & 0x8))
+ udelay(10);
+}
+
+/*
+ * Hardware start transmission.
+ * Send a packet to media from the upper layer.
+ */
+
+static int uli526x_start_xmit(struct eth_device *dev,
+ volatile void *packet, int length)
+{
+ struct uli526x_board_info *db = dev->priv;
+ struct tx_desc *txptr;
+ unsigned int len = length;
+ /* Too large packet check */
+ if (len > MAX_PACKET_SIZE) {
+ printf(": big packet = %d\n", len);
+ return 0;
+ }
+
+ /* No Tx resource check, it never happen nromally */
+ if (db->tx_packet_cnt >= TX_FREE_DESC_CNT) {
+ printf("No Tx resource %ld\n", db->tx_packet_cnt);
+ return 0;
+ }
+
+ /* Disable NIC interrupt */
+ outl(0, dev->iobase + DCR7);
+
+ /* transmit this packet */
+ txptr = db->tx_insert_ptr;
+ memcpy((char *)txptr->tx_buf_ptr, (char *)packet, (int)length);
+ txptr->tdes1 = cpu_to_le32(0xe1000000 | length);
+
+ /* Point to next transmit free descriptor */
+ db->tx_insert_ptr = txptr->next_tx_desc;
+
+ /* Transmit Packet Process */
+ if ((db->tx_packet_cnt < TX_DESC_CNT)) {
+ txptr->tdes0 = cpu_to_le32(0x80000000); /* Set owner bit */
+ db->tx_packet_cnt++; /* Ready to send */
+ outl(0x1, dev->iobase + DCR1); /* Issue Tx polling */
+ }
+
+ /* Got ULI526X status */
+ db->cr5_data = inl(db->ioaddr + DCR5);
+ outl(db->cr5_data, db->ioaddr + DCR5);
+
+#ifdef TX_DEBUG
+ printf("%s(): length = 0x%x\n", __FUNCTION__, length);
+ printf("%s(): cr5_data=%x\n", __FUNCTION__, db->cr5_data);
+#endif
+
+ outl(db->cr7_data, dev->iobase + DCR7);
+ uli526x_free_tx_pkt(dev, db);
+
+ return length;
+}
+
+/*
+ * Free TX resource after TX complete
+ */
+
+static void uli526x_free_tx_pkt(struct eth_device *dev,
+ struct uli526x_board_info *db)
+{
+ struct tx_desc *txptr;
+ u32 tdes0;
+
+ txptr = db->tx_remove_ptr;
+ while (db->tx_packet_cnt) {
+ tdes0 = le32_to_cpu(txptr->tdes0);
+ /* printf(DRV_NAME ": tdes0=%x\n", tdes0); */
+ if (tdes0 & 0x80000000)
+ break;
+
+ /* A packet sent completed */
+ db->tx_packet_cnt--;
+
+ if (tdes0 != 0x7fffffff) {
+#ifdef TX_DEBUG
+ printf("%s()tdes0=%x\n", __FUNCTION__, tdes0);
+#endif
+ if (tdes0 & TDES0_ERR_MASK) {
+ if (tdes0 & 0x0002) { /* UnderRun */
+ if (!(db->cr6_data & CR6_SFT)) {
+ db->cr6_data = db->cr6_data |
+ CR6_SFT;
+ update_cr6(db->cr6_data,
+ db->ioaddr);
+ }
+ }
+ }
+ }
+
+ txptr = txptr->next_tx_desc;
+ }/* End of while */
+
+ /* Update TX remove pointer to next */
+ db->tx_remove_ptr = txptr;
+}
+
+
+/*
+ * Receive the come packet and pass to upper layer
+ */
+
+static int uli526x_rx_packet(struct eth_device *dev)
+{
+ struct uli526x_board_info *db = dev->priv;
+ struct rx_desc *rxptr;
+ int rxlen = 0;
+ u32 rdes0;
+
+ rxptr = db->rx_ready_ptr;
+
+ rdes0 = le32_to_cpu(rxptr->rdes0);
+#ifdef RX_DEBUG
+ printf("%s(): rxptr->rdes0=%x:%x\n", __FUNCTION__, rxptr->rdes0);
+#endif
+ if (!(rdes0 & 0x80000000)) { /* packet owner check */
+ if ((rdes0 & 0x300) != 0x300) {
+ /* A packet without First/Last flag */
+ /* reuse this buf */
+ printf("A packet without First/Last flag");
+ uli526x_reuse_buf(rxptr);
+ } else {
+ /* A packet with First/Last flag */
+ rxlen = ((rdes0 >> 16) & 0x3fff) - 4;
+#ifdef RX_DEBUG
+ printf("%s(): rxlen =%x\n", __FUNCTION__, rxlen);
+#endif
+ /* error summary bit check */
+ if (rdes0 & 0x8000) {
+ /* This is a error packet */
+ printf("Eroor: rdes0: %lx\n", rdes0);
+ }
+
+ if (!(rdes0 & 0x8000) ||
+ ((db->cr6_data & CR6_PM) && (rxlen > 6))) {
+
+#ifdef RX_DEBUG
+ printf("%s(): rx_skb_ptr =%x\n",
+ __FUNCTION__, rxptr->rx_buf_ptr);
+ printf("%s(): rxlen =%x\n",
+ __FUNCTION__, rxlen);
+
+ printf("%s(): buf addr =%x\n",
+ __FUNCTION__, rxptr->rx_buf_ptr);
+ printf("%s(): rxlen =%x\n",
+ __FUNCTION__, rxlen);
+ int i;
+ for (i = 0; i < 0x20; i++)
+ printf("%s(): data[%x] =%x\n",
+ __FUNCTION__, i, rxptr->rx_buf_ptr[i]);
+#endif
+
+ NetReceive(rxptr->rx_buf_ptr, rxlen);
+ uli526x_reuse_buf(rxptr);
+
+ } else {
+ /* Reuse SKB buffer when the packet is error */
+ printf("Reuse buffer, rdes0");
+ uli526x_reuse_buf(rxptr);
+ }
+ }
+
+ rxptr = rxptr->next_rx_desc;
+ }
+
+ db->rx_ready_ptr = rxptr;
+ return rxlen;
+}
+
+/*
+ * Reuse the RX buffer
+ */
+
+static void uli526x_reuse_buf(struct rx_desc *rxptr)
+{
+
+ if (!(rxptr->rdes0 & cpu_to_le32(0x80000000)))
+ rxptr->rdes0 = cpu_to_le32(0x80000000);
+ else
+ printf("Buffer reuse method error");
+}
+/*
+ * Initialize transmit/Receive descriptor
+ * Using Chain structure, and allocate Tx/Rx buffer
+ */
+
+static void uli526x_descriptor_init(struct uli526x_board_info *db,
+ unsigned long ioaddr)
+{
+ struct tx_desc *tmp_tx;
+ struct rx_desc *tmp_rx;
+ unsigned char *tmp_buf;
+ dma_addr_t tmp_tx_dma, tmp_rx_dma;
+ dma_addr_t tmp_buf_dma;
+ int i;
+ /* tx descriptor start pointer */
+ db->tx_insert_ptr = db->first_tx_desc;
+ db->tx_remove_ptr = db->first_tx_desc;
+
+ outl(db->first_tx_desc_dma, ioaddr + DCR4); /* TX DESC address */
+
+ /* rx descriptor start pointer */
+ db->first_rx_desc = (void *)db->first_tx_desc +
+ sizeof(struct tx_desc) * TX_DESC_CNT;
+ db->first_rx_desc_dma = db->first_tx_desc_dma +
+ sizeof(struct tx_desc) * TX_DESC_CNT;
+ db->rx_ready_ptr = db->first_rx_desc;
+ outl(db->first_rx_desc_dma, ioaddr + DCR3); /* RX DESC address */
+#ifdef DEBUG
+ printf("%s(): db->first_tx_desc= 0x%x\n",
+ __FUNCTION__, db->first_tx_desc);
+ printf("%s(): db->first_rx_desc_dma= 0x%x\n",
+ __FUNCTION__, db->first_rx_desc_dma);
+#endif
+ /* Init Transmit chain */
+ tmp_buf = db->buf_pool_start;
+ tmp_buf_dma = db->buf_pool_dma_start;
+ tmp_tx_dma = db->first_tx_desc_dma;
+ for (tmp_tx = db->first_tx_desc, i = 0;
+ i < TX_DESC_CNT; i++, tmp_tx++) {
+ tmp_tx->tx_buf_ptr = tmp_buf;
+ tmp_tx->tdes0 = cpu_to_le32(0);
+ tmp_tx->tdes1 = cpu_to_le32(0x81000000); /* IC, chain */
+ tmp_tx->tdes2 = cpu_to_le32(tmp_buf_dma);
+ tmp_tx_dma += sizeof(struct tx_desc);
+ tmp_tx->tdes3 = cpu_to_le32(tmp_tx_dma);
+ tmp_tx->next_tx_desc = tmp_tx + 1;
+ tmp_buf = tmp_buf + TX_BUF_ALLOC;
+ tmp_buf_dma = tmp_buf_dma + TX_BUF_ALLOC;
+ }
+ (--tmp_tx)->tdes3 = cpu_to_le32(db->first_tx_desc_dma);
+ tmp_tx->next_tx_desc = db->first_tx_desc;
+
+ /* Init Receive descriptor chain */
+ tmp_rx_dma = db->first_rx_desc_dma;
+ for (tmp_rx = db->first_rx_desc, i = 0; i < RX_DESC_CNT;
+ i++, tmp_rx++) {
+ tmp_rx->rdes0 = cpu_to_le32(0);
+ tmp_rx->rdes1 = cpu_to_le32(0x01000600);
+ tmp_rx_dma += sizeof(struct rx_desc);
+ tmp_rx->rdes3 = cpu_to_le32(tmp_rx_dma);
+ tmp_rx->next_rx_desc = tmp_rx + 1;
+ }
+ (--tmp_rx)->rdes3 = cpu_to_le32(db->first_rx_desc_dma);
+ tmp_rx->next_rx_desc = db->first_rx_desc;
+
+ /* pre-allocate Rx buffer */
+ allocate_rx_buffer(db);
+}
+
+/*
+ * Update CR6 value
+ * Firstly stop ULI526X, then written value and start
+ */
+
+static void update_cr6(u32 cr6_data, unsigned long ioaddr)
+{
+
+ outl(cr6_data, ioaddr + DCR6);
+ udelay(5);
+}
+
+/*
+ * Allocate rx buffer,
+ */
+
+static void allocate_rx_buffer(struct uli526x_board_info *db)
+{
+ int index;
+ struct rx_desc *rxptr;
+ rxptr = db->first_rx_desc;
+ u32 addr;
+
+ for (index = 0; index < RX_DESC_CNT; index++) {
+ addr = (u32)NetRxPackets[index];
+ addr += (16 - (addr & 15));
+ rxptr->rx_buf_ptr = (char *) addr;
+ rxptr->rdes2 = cpu_to_le32(addr);
+ rxptr->rdes0 = cpu_to_le32(0x80000000);
+#ifdef DEBUG
+ printf("%s(): Number 0x%x:\n", __FUNCTION__, index);
+ printf("%s(): addr 0x%x:\n", __FUNCTION__, addr);
+ printf("%s(): rxptr address = 0x%x\n", __FUNCTION__, rxptr);
+ printf("%s(): rxptr buf address = 0x%x\n", \
+ __FUNCTION__, rxptr->rx_buf_ptr);
+ printf("%s(): rdes2 = 0x%x\n", __FUNCTION__, rxptr->rdes2);
+#endif
+ rxptr = rxptr->next_rx_desc;
+ }
+}
+
+/*
+ * Read one word data from the serial ROM
+ */
+
+static u16 read_srom_word(long ioaddr, int offset)
+{
+ int i;
+ u16 srom_data = 0;
+ long cr9_ioaddr = ioaddr + DCR9;
+
+ outl(CR9_SROM_READ, cr9_ioaddr);
+ outl(CR9_SROM_READ | CR9_SRCS, cr9_ioaddr);
+
+ /* Send the Read Command 110b */
+ SROM_CLK_WRITE(SROM_DATA_1, cr9_ioaddr);
+ SROM_CLK_WRITE(SROM_DATA_1, cr9_ioaddr);
+ SROM_CLK_WRITE(SROM_DATA_0, cr9_ioaddr);
+
+ /* Send the offset */
+ for (i = 5; i >= 0; i--) {
+ srom_data = (offset & (1 << i)) ? SROM_DATA_1 : SROM_DATA_0;
+ SROM_CLK_WRITE(srom_data, cr9_ioaddr);
+ }
+
+ outl(CR9_SROM_READ | CR9_SRCS, cr9_ioaddr);
+
+ for (i = 16; i > 0; i--) {
+ outl(CR9_SROM_READ | CR9_SRCS | CR9_SRCLK, cr9_ioaddr);
+ udelay(5);
+ srom_data = (srom_data << 1) | ((inl(cr9_ioaddr) & CR9_CRDOUT)
+ ? 1 : 0);
+ outl(CR9_SROM_READ | CR9_SRCS, cr9_ioaddr);
+ udelay(5);
+ }
+
+ outl(CR9_SROM_READ, cr9_ioaddr);
+ return srom_data;
+}
+
+/*
+ * Set 10/100 phyxcer capability
+ * AUTO mode : phyxcer register4 is NIC capability
+ * Force mode: phyxcer register4 is the force media
+ */
+
+static void uli526x_set_phyxcer(struct uli526x_board_info *db)
+{
+ u16 phy_reg;
+
+ /* Phyxcer capability setting */
+ phy_reg = phy_read(db->ioaddr, db->phy_addr, 4, db->chip_id) & ~0x01e0;
+
+ if (db->media_mode & ULI526X_AUTO) {
+ /* AUTO Mode */
+ phy_reg |= db->PHY_reg4;
+ } else {
+ /* Force Mode */
+ switch (db->media_mode) {
+ case ULI526X_10MHF: phy_reg |= 0x20; break;
+ case ULI526X_10MFD: phy_reg |= 0x40; break;
+ case ULI526X_100MHF: phy_reg |= 0x80; break;
+ case ULI526X_100MFD: phy_reg |= 0x100; break;
+ }
+
+ }
+
+ /* Write new capability to Phyxcer Reg4 */
+ if (!(phy_reg & 0x01e0)) {
+ phy_reg |= db->PHY_reg4;
+ db->media_mode |= ULI526X_AUTO;
+ }
+ phy_write(db->ioaddr, db->phy_addr, 4, phy_reg, db->chip_id);
+
+ /* Restart Auto-Negotiation */
+ phy_write(db->ioaddr, db->phy_addr, 0, 0x1200, db->chip_id);
+ udelay(50);
+}
+
+/*
+ * Write a word to Phy register
+ */
+
+static void phy_write(unsigned long iobase, u8 phy_addr, u8 offset,
+ u16 phy_data, u32 chip_id)
+{
+ u16 i;
+ unsigned long ioaddr;
+
+ if (chip_id == PCI_ULI5263_ID) {
+ phy_writeby_cr10(iobase, phy_addr, offset, phy_data);
+ return;
+ }
+ /* M5261/M5263 Chip */
+ ioaddr = iobase + DCR9;
+
+ /* Send 33 synchronization clock to Phy controller */
+ for (i = 0; i < 35; i++)
+ phy_write_1bit(ioaddr, PHY_DATA_1, chip_id);
+
+ /* Send start command(01) to Phy */
+ phy_write_1bit(ioaddr, PHY_DATA_0, chip_id);
+ phy_write_1bit(ioaddr, PHY_DATA_1, chip_id);
+
+ /* Send write command(01) to Phy */
+ phy_write_1bit(ioaddr, PHY_DATA_0, chip_id);
+ phy_write_1bit(ioaddr, PHY_DATA_1, chip_id);
+
+ /* Send Phy address */
+ for (i = 0x10; i > 0; i = i >> 1)
+ phy_write_1bit(ioaddr, phy_addr & i ?
+ PHY_DATA_1 : PHY_DATA_0, chip_id);
+
+ /* Send register address */
+ for (i = 0x10; i > 0; i = i >> 1)
+ phy_write_1bit(ioaddr, offset & i ?
+ PHY_DATA_1 : PHY_DATA_0, chip_id);
+
+ /* written trasnition */
+ phy_write_1bit(ioaddr, PHY_DATA_1, chip_id);
+ phy_write_1bit(ioaddr, PHY_DATA_0, chip_id);
+
+ /* Write a word data to PHY controller */
+ for (i = 0x8000; i > 0; i >>= 1)
+ phy_write_1bit(ioaddr, phy_data & i ?
+ PHY_DATA_1 : PHY_DATA_0, chip_id);
+}
+
+/*
+ * Read a word data from phy register
+ */
+
+static u16 phy_read(unsigned long iobase, u8 phy_addr, u8 offset, u32 chip_id)
+{
+ int i;
+ u16 phy_data;
+ unsigned long ioaddr;
+
+ if (chip_id == PCI_ULI5263_ID)
+ return phy_readby_cr10(iobase, phy_addr, offset);
+ /* M5261/M5263 Chip */
+ ioaddr = iobase + DCR9;
+
+ /* Send 33 synchronization clock to Phy controller */
+ for (i = 0; i < 35; i++)
+ phy_write_1bit(ioaddr, PHY_DATA_1, chip_id);
+
+ /* Send start command(01) to Phy */
+ phy_write_1bit(ioaddr, PHY_DATA_0, chip_id);
+ phy_write_1bit(ioaddr, PHY_DATA_1, chip_id);
+
+ /* Send read command(10) to Phy */
+ phy_write_1bit(ioaddr, PHY_DATA_1, chip_id);
+ phy_write_1bit(ioaddr, PHY_DATA_0, chip_id);
+
+ /* Send Phy address */
+ for (i = 0x10; i > 0; i = i >> 1)
+ phy_write_1bit(ioaddr, phy_addr & i ?
+ PHY_DATA_1 : PHY_DATA_0, chip_id);
+
+ /* Send register address */
+ for (i = 0x10; i > 0; i = i >> 1)
+ phy_write_1bit(ioaddr, offset & i ?
+ PHY_DATA_1 : PHY_DATA_0, chip_id);
+
+ /* Skip transition state */
+ phy_read_1bit(ioaddr, chip_id);
+
+ /* read 16bit data */
+ for (phy_data = 0, i = 0; i < 16; i++) {
+ phy_data <<= 1;
+ phy_data |= phy_read_1bit(ioaddr, chip_id);
+ }
+
+ return phy_data;
+}
+
+static u16 phy_readby_cr10(unsigned long iobase, u8 phy_addr, u8 offset)
+{
+ unsigned long ioaddr, cr10_value;
+
+ ioaddr = iobase + DCR10;
+ cr10_value = phy_addr;
+ cr10_value = (cr10_value<<5) + offset;
+ cr10_value = (cr10_value<<16) + 0x08000000;
+ outl(cr10_value, ioaddr);
+ udelay(1);
+ while (1) {
+ cr10_value = inl(ioaddr);
+ if (cr10_value & 0x10000000)
+ break;
+ }
+ return (cr10_value&0x0ffff);
+}
+
+static void phy_writeby_cr10(unsigned long iobase, u8 phy_addr,
+ u8 offset, u16 phy_data)
+{
+ unsigned long ioaddr, cr10_value;
+
+ ioaddr = iobase + DCR10;
+ cr10_value = phy_addr;
+ cr10_value = (cr10_value<<5) + offset;
+ cr10_value = (cr10_value<<16) + 0x04000000 + phy_data;
+ outl(cr10_value, ioaddr);
+ udelay(1);
+}
+/*
+ * Write one bit data to Phy Controller
+ */
+
+static void phy_write_1bit(unsigned long ioaddr, u32 phy_data, u32 chip_id)
+{
+ outl(phy_data , ioaddr); /* MII Clock Low */
+ udelay(1);
+ outl(phy_data | MDCLKH, ioaddr); /* MII Clock High */
+ udelay(1);
+ outl(phy_data , ioaddr); /* MII Clock Low */
+ udelay(1);
+}
+
+/*
+ * Read one bit phy data from PHY controller
+ */
+
+static u16 phy_read_1bit(unsigned long ioaddr, u32 chip_id)
+{
+ u16 phy_data;
+
+ outl(0x50000 , ioaddr);
+ udelay(1);
+ phy_data = (inl(ioaddr) >> 19) & 0x1;
+ outl(0x40000 , ioaddr);
+ udelay(1);
+
+ return phy_data;
+}
+
+/*
+ * Set MAC address to ID Table
+ */
+
+static void set_mac_addr(struct eth_device *dev)
+{
+ int i;
+ u16 addr;
+ struct uli526x_board_info *db = dev->priv;
+ outl(0x10000, db->ioaddr + DCR0); /* Diagnosis mode */
+ /* Reset dianostic pointer port */
+ outl(0x1c0, db->ioaddr + DCR13);
+ outl(0, db->ioaddr + DCR14); /* Clear reset port */
+ outl(0x10, db->ioaddr + DCR14); /* Reset ID Table pointer */
+ outl(0, db->ioaddr + DCR14); /* Clear reset port */
+ outl(0, db->ioaddr + DCR13); /* Clear CR13 */
+ /* Select ID Table access port */
+ outl(0x1b0, db->ioaddr + DCR13);
+ /* Read MAC address from CR14 */
+ for (i = 0; i < 3; i++) {
+ addr = dev->enetaddr[2 * i] | (dev->enetaddr[2 * i + 1] << 8);
+ outl(addr, db->ioaddr + DCR14);
+ }
+ /* write end */
+ outl(0, db->ioaddr + DCR13); /* Clear CR13 */
+ outl(0, db->ioaddr + DCR0); /* Clear CR0 */
+ udelay(10);
+ return;
+}
+#endif
diff --git a/drivers/usb_ohci.c b/drivers/usb_ohci.c
index 14984a5f39..cfa384eff6 100644
--- a/drivers/usb_ohci.c
+++ b/drivers/usb_ohci.c
@@ -59,6 +59,10 @@
#include <usb.h>
#include "usb_ohci.h"
+#ifdef CONFIG_AT91RM9200
+#include <asm/arch/hardware.h> /* needed for AT91_USB_HOST_BASE */
+#endif
+
#if defined(CONFIG_ARM920T) || \
defined(CONFIG_S3C2400) || \
defined(CONFIG_S3C2410) || \
@@ -93,6 +97,7 @@
#ifdef CONFIG_PCI_OHCI
static struct pci_device_id ohci_pci_ids[] = {
{0x10b9, 0x5237}, /* ULI1575 PCI OHCI module ids */
+ {0x1033, 0x0035}, /* NEC PCI OHCI module ids */
/* Please add supported PCI OHCI controller ids here */
{0, 0}
};
OpenPOWER on IntegriCloud