diff options
| -rw-r--r-- | CHANGELOG | 7 | ||||
| -rw-r--r-- | Makefile | 3 | ||||
| -rw-r--r-- | board/cmc_pu2/Makefile | 47 | ||||
| -rw-r--r-- | board/cmc_pu2/at45.c | 621 | ||||
| -rw-r--r-- | board/cmc_pu2/at91rm9200dk.c | 118 | ||||
| -rw-r--r-- | board/cmc_pu2/config.mk | 1 | ||||
| -rw-r--r-- | board/cmc_pu2/dm9161.c | 243 | ||||
| -rw-r--r-- | board/cmc_pu2/flash.c | 507 | ||||
| -rw-r--r-- | board/cmc_pu2/memsetup.S | 200 | ||||
| -rw-r--r-- | board/cmc_pu2/u-boot.lds | 56 | ||||
| -rw-r--r-- | cpu/at91rm9200/Makefile | 2 | ||||
| -rw-r--r-- | cpu/at91rm9200/cpu.c | 7 | ||||
| -rw-r--r-- | cpu/at91rm9200/i2c.c | 192 | ||||
| -rw-r--r-- | cpu/at91rm9200/serial.c | 25 | ||||
| -rw-r--r-- | include/asm-arm/arch-at91rm9200/AT91RM9200.h | 56 | ||||
| -rw-r--r-- | include/at91rm9200_i2c.h | 126 | ||||
| -rw-r--r-- | include/configs/cmc_pu2.h | 225 | 
17 files changed, 2421 insertions, 15 deletions
| @@ -2,6 +2,13 @@  Changes since U-Boot 1.1.1:  ====================================================================== +* Patch by Gary Jennejohn, 01 Oct 2004: +  - add support for CMC PU2 board +  - add support for I2C on at91rm9200 + +* Patch by Gary Jennejohn, 28 Sep 2004: +  fix baudrate handling on at91rm9200 +  * Patch by Yuli Barcohen, 22 Aug 2004:    - remove ZPC.1900 board-specific flash driver;      switch the port to generic CFI driver; @@ -1294,6 +1294,9 @@ evb4510_config :	unconfig  at91rm9200dk_config	:	unconfig  	@./mkconfig $(@:_config=) arm at91rm9200 at91rm9200dk +cmc_pu2_config	:	unconfig +	@./mkconfig $(@:_config=) arm at91rm9200 cmc_pu2 +  #########################################################################  ## XScale Systems  ######################################################################### diff --git a/board/cmc_pu2/Makefile b/board/cmc_pu2/Makefile new file mode 100644 index 000000000..f94bd990d --- /dev/null +++ b/board/cmc_pu2/Makefile @@ -0,0 +1,47 @@ +# +# (C) Copyright 2003 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# 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	= lib$(BOARD).a + +OBJS	:= at91rm9200dk.o at45.o dm9161.o flash.o +SOBJS	:= memsetup.o + +$(LIB):	$(OBJS) $(SOBJS) +	$(AR) crv $@ $(OBJS) $(SOBJS) + +clean: +	rm -f $(SOBJS) $(OBJS) + +distclean:	clean +	rm -f $(LIB) core *.bak .depend + +######################################################################### + +.depend:	Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c) +		$(CC) -M $(CPPFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@ + +-include .depend + +######################################################################### diff --git a/board/cmc_pu2/at45.c b/board/cmc_pu2/at45.c new file mode 100644 index 000000000..3c0013216 --- /dev/null +++ b/board/cmc_pu2/at45.c @@ -0,0 +1,621 @@ +/* Driver for ATMEL DataFlash support + * Author : Hamid Ikdoumi (Atmel) + * + * 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 <config.h> +#include <common.h> +#include <asm/hardware.h> + +#ifdef CONFIG_HAS_DATAFLASH +#include <dataflash.h> + +#define AT91C_SPI_CLK	10000000	/* Max Value = 10MHz to be compliant to +the Continuous Array Read function */ + +/* AC Characteristics */ +/* DLYBS = tCSS = 250ns min and DLYBCT = tCSH = 250ns */ +#define DATAFLASH_TCSS	(0xC << 16) +#define DATAFLASH_TCHS	(0x1 << 24) + +#define AT91C_TIMEOUT_WRDY			200000 +#define AT91C_SPI_PCS0_SERIAL_DATAFLASH		0xE     /* Chip Select 0 : NPCS0 %1110 */ +#define AT91C_SPI_PCS3_DATAFLASH_CARD		0x7     /* Chip Select 3 : NPCS3 %0111 */ + +void AT91F_SpiInit(void) { + +/*-------------------------------------------------------------------*/ +/*	SPI DataFlash Init								*/ +/*-------------------------------------------------------------------*/ +	/* Configure PIOs */ +	AT91C_BASE_PIOA->PIO_ASR = AT91C_PA3_NPCS0 | AT91C_PA4_NPCS1 | AT91C_PA1_MOSI | AT91C_PA5_NPCS2 | +				   AT91C_PA6_NPCS3 | AT91C_PA0_MISO | AT91C_PA2_SPCK; +	AT91C_BASE_PIOA->PIO_PDR = AT91C_PA3_NPCS0 | AT91C_PA4_NPCS1 | AT91C_PA1_MOSI | AT91C_PA5_NPCS2 | +				   AT91C_PA6_NPCS3 | AT91C_PA0_MISO | AT91C_PA2_SPCK; +	/* Enable CLock */ +	AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_SPI; + +	/* Reset the SPI */ +	AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SWRST; + +	/* Configure SPI in Master Mode with No CS selected !!! */ +	AT91C_BASE_SPI->SPI_MR = AT91C_SPI_MSTR | AT91C_SPI_MODFDIS | AT91C_SPI_PCS; + +	/* Configure CS0 and CS3 */ +	*(AT91C_SPI_CSR + 0) = AT91C_SPI_CPOL | (AT91C_SPI_DLYBS & DATAFLASH_TCSS) | (AT91C_SPI_DLYBCT & +	DATAFLASH_TCHS) | ((AT91C_MASTER_CLOCK / (2*AT91C_SPI_CLK)) << 8); + +	*(AT91C_SPI_CSR + 3) = AT91C_SPI_CPOL | (AT91C_SPI_DLYBS & DATAFLASH_TCSS) | (AT91C_SPI_DLYBCT & +	DATAFLASH_TCHS) | ((AT91C_MASTER_CLOCK / (2*AT91C_SPI_CLK)) << 8); + +} + +void AT91F_SpiEnable(int cs) { +	switch(cs) { +	case 0:	/* Configure SPI CS0 for Serial DataFlash AT45DBxx */ +		AT91C_BASE_SPI->SPI_MR &= 0xFFF0FFFF; +		AT91C_BASE_SPI->SPI_MR |= ((AT91C_SPI_PCS0_SERIAL_DATAFLASH<<16) & AT91C_SPI_PCS); +		break; +	case 3:	/* Configure SPI CS3 for Serial DataFlash Card */ +		/* Set up PIO SDC_TYPE to switch on DataFlash Card and not MMC/SDCard */ +		AT91C_BASE_PIOB->PIO_PER = AT91C_PIO_PB7;	/* Set in PIO mode */ +		AT91C_BASE_PIOB->PIO_OER = AT91C_PIO_PB7;	/* Configure in output */ +		/* Clear Output */ +		AT91C_BASE_PIOB->PIO_CODR = AT91C_PIO_PB7; +		/* Configure PCS */ +		AT91C_BASE_SPI->SPI_MR &= 0xFFF0FFFF; +		AT91C_BASE_SPI->SPI_MR |= ((AT91C_SPI_PCS3_DATAFLASH_CARD<<16) & AT91C_SPI_PCS); +		break; +	} + +	/* SPI_Enable */ +	AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SPIEN; +} + +/*----------------------------------------------------------------------------*/ +/* \fn    AT91F_SpiWrite						      */ +/* \brief Set the PDC registers for a transfert				      */ +/*----------------------------------------------------------------------------*/ +unsigned int AT91F_SpiWrite ( AT91PS_DataflashDesc pDesc ) +{ +	unsigned int timeout; + +	pDesc->state = BUSY; + +	AT91C_BASE_SPI->SPI_PTCR = AT91C_PDC_TXTDIS + AT91C_PDC_RXTDIS; + +	/* Initialize the Transmit and Receive Pointer */ +	AT91C_BASE_SPI->SPI_RPR = (unsigned int)pDesc->rx_cmd_pt ; +	AT91C_BASE_SPI->SPI_TPR = (unsigned int)pDesc->tx_cmd_pt ; + +	/* Intialize the Transmit and Receive Counters */ +	AT91C_BASE_SPI->SPI_RCR = pDesc->rx_cmd_size; +	AT91C_BASE_SPI->SPI_TCR = pDesc->tx_cmd_size; + +	if ( pDesc->tx_data_size != 0 ) { +		/* Initialize the Next Transmit and Next Receive Pointer */ +		AT91C_BASE_SPI->SPI_RNPR = (unsigned int)pDesc->rx_data_pt ; +		AT91C_BASE_SPI->SPI_TNPR = (unsigned int)pDesc->tx_data_pt ; + +		/* Intialize the Next Transmit and Next Receive Counters */ +		AT91C_BASE_SPI->SPI_RNCR = pDesc->rx_data_size ; +		AT91C_BASE_SPI->SPI_TNCR = pDesc->tx_data_size ; +	} + +	/* arm simple, non interrupt dependent timer */ +	reset_timer_masked(); +	timeout = 0; + +	AT91C_BASE_SPI->SPI_PTCR = AT91C_PDC_TXTEN + AT91C_PDC_RXTEN; +	while(!(AT91C_BASE_SPI->SPI_SR & AT91C_SPI_RXBUFF) && ((timeout = get_timer_masked() ) < CFG_SPI_WRITE_TOUT)); +	AT91C_BASE_SPI->SPI_PTCR = AT91C_PDC_TXTDIS + AT91C_PDC_RXTDIS; +	pDesc->state = IDLE; + +	if (timeout >= CFG_SPI_WRITE_TOUT){ +		printf("Error Timeout\n\r"); +		return DATAFLASH_ERROR; +	} + +	return DATAFLASH_OK; +} + + +/*----------------------------------------------------------------------*/ +/* \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) +{ +    unsigned int adr; + +	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)); + +	/* fill the  command  buffer */ +	pDataFlash->pDataFlashDesc->command[0] = OpCode; +	if (pDataFlash->pDevice->pages_number >= 16384) { +		pDataFlash->pDataFlashDesc->command[1] = (unsigned char)((adr & 0x0F000000) >> 24); +		pDataFlash->pDataFlashDesc->command[2] = (unsigned char)((adr & 0x00FF0000) >> 16); +		pDataFlash->pDataFlashDesc->command[3] = (unsigned char)((adr & 0x0000FF00) >> 8); +		pDataFlash->pDataFlashDesc->command[4] = (unsigned char)(adr & 0x000000FF); +	} else { +		pDataFlash->pDataFlashDesc->command[1] = (unsigned char)((adr & 0x00FF0000) >> 16); +		pDataFlash->pDataFlashDesc->command[2] = (unsigned char)((adr & 0x0000FF00) >> 8); +		pDataFlash->pDataFlashDesc->command[3] = (unsigned char)(adr & 0x000000FF) ; +		pDataFlash->pDataFlashDesc->command[4] = 0; +	} +	pDataFlash->pDataFlashDesc->command[5] = 0; +	pDataFlash->pDataFlashDesc->command[6] = 0; +	pDataFlash->pDataFlashDesc->command[7] = 0; + +	/* Initialize the SpiData structure for the spi write fuction */ +	pDataFlash->pDataFlashDesc->tx_cmd_pt   =  pDataFlash->pDataFlashDesc->command ; +	pDataFlash->pDataFlashDesc->tx_cmd_size =  CmdSize ; +	pDataFlash->pDataFlashDesc->rx_cmd_pt   =  pDataFlash->pDataFlashDesc->command ; +	pDataFlash->pDataFlashDesc->rx_cmd_size =  CmdSize ; + +	/* send the command and read the data */ +	return AT91F_SpiWrite (pDataFlash->pDataFlashDesc); +} + + +/*----------------------------------------------------------------------*/ +/* \fn    AT91F_DataFlashGetStatus					*/ +/* \brief Read the status register of the dataflash			*/ +/*----------------------------------------------------------------------*/ +AT91S_DataFlashStatus AT91F_DataFlashGetStatus(AT91PS_DataflashDesc pDesc) +{ +	AT91S_DataFlashStatus status; + +	/* if a transfert is in progress ==> return 0 */ +	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 = *( (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->DataFlash_state = IDLE; + +	do { +		AT91F_DataFlashGetStatus(pDataFlashDesc); +		timeout--; +	} while( ((pDataFlashDesc->DataFlash_state & 0x80) != 0x80) && (timeout > 0) ); + +	if((pDataFlashDesc->DataFlash_state & 0x80) != 0x80) +		return DATAFLASH_ERROR; + +	return DATAFLASH_OK; +} + + +/*------------------------------------------------------------------------------*/ +/* Function Name       : AT91F_DataFlashContinuousRead 				*/ +/* Object              : Continuous stream Read 				*/ +/* Input Parameters    : DataFlash Service					*/ +/*						: <src> = dataflash address	*/ +/*                     : <*dataBuffer> = data buffer pointer			*/ +/*                     : <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 status; +	/* Test the size to read in the device */ +	if ( (src + sizeToRead) > (pDataFlash->pDevice->pages_size * (pDataFlash->pDevice->pages_number))) +		return DATAFLASH_MEMORY_OVERFLOW; + +	pDataFlash->pDataFlashDesc->rx_data_pt = dataBuffer; +	pDataFlash->pDataFlashDesc->rx_data_size = sizeToRead; +	pDataFlash->pDataFlashDesc->tx_data_pt = dataBuffer; +	pDataFlash->pDataFlashDesc->tx_data_size = sizeToRead; + +	status = AT91F_DataFlashSendCommand (pDataFlash, DB_CONTINUOUS_ARRAY_READ, 8, src); +	/* Send the command to the dataflash */ +	return(status); +} + + +/*------------------------------------------------------------------------------*/ +/* Function Name       : AT91F_DataFlashPagePgmBuf				*/ +/* Object              : Main memory page program through buffer 1 or buffer 2	*/ +/* Input Parameters    : DataFlash Service					*/ +/*						: <*src> = Source buffer	*/ +/*                     : <dest> = dataflash destination address			*/ +/*                     : <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) +{ +	int cmdsize; +	pDataFlash->pDataFlashDesc->tx_data_pt = src ; +	pDataFlash->pDataFlashDesc->tx_data_size = SizeToWrite ; +	pDataFlash->pDataFlashDesc->rx_data_pt = src; +	pDataFlash->pDataFlashDesc->rx_data_size = SizeToWrite; + +	cmdsize = 4; +	/* Send the command to the dataflash */ +	if (pDataFlash->pDevice->pages_number >= 16384) +		cmdsize = 5; +	return(AT91F_DataFlashSendCommand (pDataFlash, DB_PAGE_PGM_BUF1, cmdsize, dest)); +} + + +/*------------------------------------------------------------------------------*/ +/* Function Name       : AT91F_MainMemoryToBufferTransfert			*/ +/* Object              : Read a page in the SRAM Buffer 1 or 2			*/ +/* Input Parameters    : DataFlash Service					*/ +/*                     : Page concerned						*/ +/*                     : 							*/ +/* Return value		: State of the dataflash				*/ +/*------------------------------------------------------------------------------*/ +AT91S_DataFlashStatus AT91F_MainMemoryToBufferTransfert( +	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)) +		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)); +} + + +/*----------------------------------------------------------------------------- */ +/* Function Name       : AT91F_DataFlashWriteBuffer				*/ +/* Object              : Write data to the internal sram buffer 1 or 2		*/ +/* Input Parameters    : DataFlash Service					*/ +/*			: <BufferCommand> = command to write buffer1 or buffer2	*/ +/*                     : <*dataBuffer> = data buffer to write			*/ +/*                     : <bufferAddress> = address in the internal buffer	*/ +/*                     : <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 ) +{ +	int cmdsize; +	/* Test if the buffer command is legal */ +	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) +		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] = (unsigned char)(((unsigned int)(bufferAddress &  pDataFlash->pDevice->byte_mask)) >> 8) ; +	    	pDataFlash->pDataFlashDesc->command[4] = (unsigned char)((unsigned int)bufferAddress  & 0x00FF) ; +		cmdsize = 5; +	} else { +	    	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; +		cmdsize = 4; +	} + +	pDataFlash->pDataFlashDesc->tx_cmd_pt 	 = pDataFlash->pDataFlashDesc->command ; +	pDataFlash->pDataFlashDesc->tx_cmd_size = cmdsize ; +	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 ; + +	return AT91F_SpiWrite(pDataFlash->pDataFlashDesc); +} + +/*------------------------------------------------------------------------------*/ +/* Function Name       : AT91F_PageErase                                        */ +/* Object              : Erase a page 						*/ +/* Input Parameters    : DataFlash Service					*/ +/*                     : Page concerned						*/ +/*                     : 							*/ +/* Return value		: State of the dataflash				*/ +/*------------------------------------------------------------------------------*/ +AT91S_DataFlashStatus AT91F_PageErase( +	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; + +	cmdsize = 4; +	if (pDataFlash->pDevice->pages_number >= 16384) +		cmdsize = 5; +	return(AT91F_DataFlashSendCommand (pDataFlash, DB_PAGE_ERASE, cmdsize, page*pDataFlash->pDevice->pages_size)); +} + + +/*------------------------------------------------------------------------------*/ +/* Function Name       : AT91F_BlockErase                                       */ +/* Object              : Erase a Block 						*/ +/* Input Parameters    : DataFlash Service					*/ +/*                     : Page concerned						*/ +/*                     : 							*/ +/* Return value		: State of the dataflash				*/ +/*------------------------------------------------------------------------------*/ +AT91S_DataFlashStatus AT91F_BlockErase( +	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; +	cmdsize = 4; +	if (pDataFlash->pDevice->pages_number >= 16384) +		cmdsize = 5; +	return(AT91F_DataFlashSendCommand (pDataFlash, DB_BLOCK_ERASE,cmdsize, block*8*pDataFlash->pDevice->pages_size)); +} + +/*------------------------------------------------------------------------------*/ +/* Function Name       : AT91F_WriteBufferToMain				*/ +/* Object              : Write buffer to the main memory			*/ +/* Input Parameters    : DataFlash Service					*/ +/*		: <BufferCommand> = command to send to buffer1 or buffer2	*/ +/*                     : <dest> = main memory address				*/ +/* Return value		: State of the dataflash				*/ +/*------------------------------------------------------------------------------*/ +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) ) +		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; +	/* Send the command to the dataflash */ +	return(AT91F_DataFlashSendCommand (pDataFlash, BufferCommand, cmdsize, dest)); +} + + +/*------------------------------------------------------------------------------*/ +/* Function Name       : AT91F_PartialPageWrite					*/ +/* Object              : Erase partielly a page					*/ +/* Input Parameters    : <page> = page number					*/ +/*			: <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) +{ +	unsigned int page; +	unsigned int AdrInPage; + +	page = dest / (pDataFlash->pDevice->pages_size); +	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_DataFlashWaitReady(pDataFlash->pDataFlashDesc, AT91C_TIMEOUT_WRDY); +	/*Update the SRAM buffer */ +	AT91F_DataFlashWriteBuffer(pDataFlash, DB_BUF1_WRITE, src, AdrInPage, size); + +	AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc, AT91C_TIMEOUT_WRDY); + +	/* Erase page if a 128 Mbits device */ +	if (pDataFlash->pDevice->pages_number >= 16384) { +		AT91F_PageErase(pDataFlash, page); +		/* Rewrite the modified Sram Buffer in the main memory */ +		AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc, 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))); +} + + +/*------------------------------------------------------------------------------*/ +/* Function Name       : AT91F_DataFlashWrite					*/ +/* Object              :							*/ +/* Input Parameters    : <*src> = Source buffer					*/ +/*                     : <dest> = dataflash adress				*/ +/*                     : <size> = data buffer size				*/ +/*------------------------------------------------------------------------------*/ +AT91S_DataFlashStatus AT91F_DataFlashWrite( +	AT91PS_DataFlash pDataFlash, +	unsigned char *src, +	int dest, +	int size ) +{ +	unsigned int length; +	unsigned int page; +	unsigned int status; + +	AT91F_SpiEnable(pDataFlash->pDevice->cs); + +	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 (size < length) +			length = size; + +		if(!AT91F_PartialPageWrite(pDataFlash,src, dest, length)) +			return DATAFLASH_ERROR; + +		AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc, AT91C_TIMEOUT_WRDY); + +		/* Update size, source and destination pointers */ +		size -= length; +		dest += length; +		src += length; +	} + +	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); +		AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc, AT91C_TIMEOUT_WRDY); + +		status = AT91F_PageErase(pDataFlash, page); +		AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc, AT91C_TIMEOUT_WRDY); +		if (!status) +			return DATAFLASH_ERROR; + +		status = AT91F_WriteBufferToMain (pDataFlash, DB_BUF1_PAGE_PGM, dest); +		if(!status) +			return DATAFLASH_ERROR; + +		AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc, AT91C_TIMEOUT_WRDY); + +		/* Update size, source and destination pointers */ +		size -= pDataFlash->pDevice->pages_size ; +		dest += pDataFlash->pDevice->pages_size ; +		src  += pDataFlash->pDevice->pages_size ; +	} + +	/* If still some bytes to read */ +	if ( size > 0 ) { +		/* program dataflash page */ +		if(!AT91F_PartialPageWrite(pDataFlash, src, dest, size) ) +			return DATAFLASH_ERROR; + +		AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc, 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) +{ +	unsigned long SizeToRead; + +	AT91F_SpiEnable(pDataFlash->pDevice->cs); + +	if(AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc, AT91C_TIMEOUT_WRDY) != DATAFLASH_OK) +		return -1; + +	while (size) { +		SizeToRead = (size < 0x8000)? size:0x8000; + +		if (AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc, AT91C_TIMEOUT_WRDY) != DATAFLASH_OK) +			return -1; + +		if (AT91F_DataFlashContinuousRead (pDataFlash, addr, buffer, SizeToRead) != DATAFLASH_OK) +			return -1; + +		size -= SizeToRead; +		addr += SizeToRead; +		buffer += SizeToRead; +	} + +	return DATAFLASH_OK; +} + + +/*------------------------------------------------------------------------------*/ +/* Function Name       : AT91F_DataflashProbe 					*/ +/* Object              : 							*/ +/* Input Parameters    : 							*/ +/* Return value	       : Dataflash status register				*/ +/*------------------------------------------------------------------------------*/ +int AT91F_DataflashProbe(int cs, AT91PS_DataflashDesc pDesc) +{ +	AT91F_SpiEnable(cs); +	AT91F_DataFlashGetStatus(pDesc); +	return((pDesc->command[1] == 0xFF)? 0: pDesc->command[1] & 0x3C); +} + +#endif diff --git a/board/cmc_pu2/at91rm9200dk.c b/board/cmc_pu2/at91rm9200dk.c new file mode 100644 index 000000000..606ea4881 --- /dev/null +++ b/board/cmc_pu2/at91rm9200dk.c @@ -0,0 +1,118 @@ +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * 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 <common.h> +#include <asm/arch/AT91RM9200.h> + +/* ------------------------------------------------------------------------- */ +/* + * Miscelaneous platform dependent initialisations + */ + +int board_init (void) +{ +	DECLARE_GLOBAL_DATA_PTR; + +	/* Enable Ctrlc */ +	console_init_f (); + +	/* Correct IRDA resistor problem */ +	/* Set PA23_TXD in Output */ +	(AT91PS_PIO) AT91C_BASE_PIOA->PIO_OER = AT91C_PA23_TXD2; + +	/* memory and cpu-speed are setup before relocation */ +	/* so we do _nothing_ here */ + +	/* arch number of AT91RM9200DK-Board */ +	gd->bd->bi_arch_number = 251; +	/* adress of boot parameters */ +	gd->bd->bi_boot_params = PHYS_SDRAM + 0x100; + +	return 0; +} + +int dram_init (void) +{ +	DECLARE_GLOBAL_DATA_PTR; + +	gd->bd->bi_dram[0].start = PHYS_SDRAM; +	gd->bd->bi_dram[0].size = PHYS_SDRAM_SIZE; +	return 0; +} + +/* + * Disk On Chip (NAND) Millenium initialization. + * The NAND lives in the CS2* space + */ +#if (CONFIG_COMMANDS & CFG_CMD_NAND) +extern ulong nand_probe (ulong physadr); + +#define AT91_SMARTMEDIA_BASE 0x40000000	/* physical address to access memory on NCS3 */ +void nand_init (void) +{ +	/* Setup Smart Media, fitst enable the address range of CS3 */ +	*AT91C_EBI_CSA |= AT91C_EBI_CS3A_SMC_SmartMedia; +	/* set the bus interface characteristics based on +	   tDS Data Set up Time 30 - ns +	   tDH Data Hold Time 20 - ns +	   tALS ALE Set up Time 20 - ns +	   16ns at 60 MHz ~= 3  */ +/*memory mapping structures */ +#define SM_ID_RWH	(5 << 28) +#define SM_RWH		(1 << 28) +#define SM_RWS		(0 << 24) +#define SM_TDF		(1 << 8) +#define SM_NWS		(3) +	AT91C_BASE_SMC2->SMC2_CSR[3] = (SM_RWH | SM_RWS | +		AT91C_SMC2_ACSS_STANDARD | AT91C_SMC2_DBW_8 | +		SM_TDF | AT91C_SMC2_WSEN | SM_NWS); + +	/* enable the SMOE line PC0=SMCE, A21=CLE, A22=ALE */ +	*AT91C_PIOC_ASR = AT91C_PC0_BFCK | AT91C_PC1_BFRDY_SMOE | +		AT91C_PC3_BFBAA_SMWE; +	*AT91C_PIOC_PDR = AT91C_PC0_BFCK | AT91C_PC1_BFRDY_SMOE | +		AT91C_PC3_BFBAA_SMWE; + +	/* Configure PC2 as input (signal READY of the SmartMedia) */ +	*AT91C_PIOC_PER = AT91C_PC2_BFAVD;	/* enable direct output enable */ +	*AT91C_PIOC_ODR = AT91C_PC2_BFAVD;	/* disable output */ + +	/* Configure PB1 as input (signal Card Detect of the SmartMedia) */ +	*AT91C_PIOB_PER = AT91C_PIO_PB1;	/* enable direct output enable */ +	*AT91C_PIOB_ODR = AT91C_PIO_PB1;	/* disable output */ + +	/* PIOB and PIOC clock enabling */ +	*AT91C_PMC_PCER = 1 << AT91C_ID_PIOB; +	*AT91C_PMC_PCER = 1 << AT91C_ID_PIOC; + +	if (*AT91C_PIOB_PDSR & AT91C_PIO_PB1) +		printf ("  No SmartMedia card inserted\n"); +#ifdef DEBUG +	printf ("  SmartMedia card inserted\n"); + +	printf ("Probing at 0x%.8x\n", AT91_SMARTMEDIA_BASE); +#endif +	printf ("%4lu MB\n", nand_probe(AT91_SMARTMEDIA_BASE) >> 20); +} +#endif diff --git a/board/cmc_pu2/config.mk b/board/cmc_pu2/config.mk new file mode 100644 index 000000000..9ce161e55 --- /dev/null +++ b/board/cmc_pu2/config.mk @@ -0,0 +1 @@ +TEXT_BASE = 0x21f00000 diff --git a/board/cmc_pu2/dm9161.c b/board/cmc_pu2/dm9161.c new file mode 100644 index 000000000..73537c037 --- /dev/null +++ b/board/cmc_pu2/dm9161.c @@ -0,0 +1,243 @@ +/* + * (C) Copyright 2003 + * Author : Hamid Ikdoumi (Atmel) + * + * 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 <at91rm9200_net.h> +#include <net.h> +#include <dm9161.h> + +#ifdef CONFIG_DRIVER_ETHER + +#if (CONFIG_COMMANDS & CFG_CMD_NET) + +/* + * Name: + *	dm9161_IsPhyConnected + * Description: + *	Reads the 2 PHY ID registers + * Arguments: + *	p_mac - pointer to AT91S_EMAC struct + * Return value: + *	TRUE - if id read successfully + *	FALSE- if error + */ +static unsigned int dm9161_IsPhyConnected (AT91PS_EMAC p_mac) +{ +	unsigned short Id1, Id2; + +	at91rm9200_EmacEnableMDIO (p_mac); +	at91rm9200_EmacReadPhy (p_mac, DM9161_PHYID1, &Id1); +	at91rm9200_EmacReadPhy (p_mac, DM9161_PHYID2, &Id2); +	at91rm9200_EmacDisableMDIO (p_mac); + +	if ((Id1 == (DM9161_PHYID1_OUI >> 6)) && +		((Id2 >> 10) == (DM9161_PHYID1_OUI & DM9161_LSB_MASK))) +		return TRUE; + +	return FALSE; +} + +/* + * Name: + *	dm9161_GetLinkSpeed + * Description: + *	Link parallel detection status of MAC is checked and set in the + *	MAC configuration registers + * Arguments: + *	p_mac - pointer to MAC + * Return value: + *	TRUE - if link status set succesfully + *	FALSE - if link status not set + */ +static UCHAR dm9161_GetLinkSpeed (AT91PS_EMAC p_mac) +{ +	unsigned short stat1, stat2; + +	if (!at91rm9200_EmacReadPhy (p_mac, DM9161_BMSR, &stat1)) +		return FALSE; + +	if (!(stat1 & DM9161_LINK_STATUS))	/* link status up? */ +		return FALSE; + +	if (!at91rm9200_EmacReadPhy (p_mac, DM9161_DSCSR, &stat2)) +		return FALSE; + +	if ((stat1 & DM9161_100BASE_TX_FD) && (stat2 & DM9161_100FDX)) { +		/*set Emac for 100BaseTX and Full Duplex  */ +		p_mac->EMAC_CFG |= AT91C_EMAC_SPD | AT91C_EMAC_FD; +		return TRUE; +	} + +	if ((stat1 & DM9161_10BASE_T_FD) && (stat2 & DM9161_10FDX)) { +		/*set MII for 10BaseT and Full Duplex  */ +		p_mac->EMAC_CFG = (p_mac->EMAC_CFG & +				~(AT91C_EMAC_SPD | AT91C_EMAC_FD)) +				| AT91C_EMAC_FD; +		return TRUE; +	} + +	if ((stat1 & DM9161_100BASE_T4_HD) && (stat2 & DM9161_100HDX)) { +		/*set MII for 100BaseTX and Half Duplex  */ +		p_mac->EMAC_CFG = (p_mac->EMAC_CFG & +				~(AT91C_EMAC_SPD | AT91C_EMAC_FD)) +				| AT91C_EMAC_SPD; +		return TRUE; +	} + +	if ((stat1 & DM9161_10BASE_T_HD) && (stat2 & DM9161_10HDX)) { +		/*set MII for 10BaseT and Half Duplex  */ +		p_mac->EMAC_CFG &= ~(AT91C_EMAC_SPD | AT91C_EMAC_FD); +		return TRUE; +	} +	return FALSE; +} + + +/* + * Name: + *	dm9161_InitPhy + * Description: + *	MAC starts checking its link by using parallel detection and + *	Autonegotiation and the same is set in the MAC configuration registers + * Arguments: + *	p_mac - pointer to struct AT91S_EMAC + * Return value: + *	TRUE - if link status set succesfully + *	FALSE - if link status not set + */ +static UCHAR dm9161_InitPhy (AT91PS_EMAC p_mac) +{ +	UCHAR ret = TRUE; +	unsigned short IntValue; + +	at91rm9200_EmacEnableMDIO (p_mac); + +	if (!dm9161_GetLinkSpeed (p_mac)) { +		/* Try another time */ +		ret = dm9161_GetLinkSpeed (p_mac); +	} + +	/* Disable PHY Interrupts */ +	at91rm9200_EmacReadPhy (p_mac, DM9161_MDINTR, &IntValue); +	/* clear FDX, SPD, Link, INTR masks */ +	IntValue &= ~(DM9161_FDX_MASK | DM9161_SPD_MASK | +		      DM9161_LINK_MASK | DM9161_INTR_MASK); +	at91rm9200_EmacWritePhy (p_mac, DM9161_MDINTR, &IntValue); +	at91rm9200_EmacDisableMDIO (p_mac); + +	return (ret); +} + + +/* + * Name: + *	dm9161_AutoNegotiate + * Description: + *	MAC Autonegotiates with the partner status of same is set in the + *	MAC configuration registers + * Arguments: + *	dev - pointer to struct net_device + * Return value: + *	TRUE - if link status set successfully + *	FALSE - if link status not set + */ +static UCHAR dm9161_AutoNegotiate (AT91PS_EMAC p_mac, int *status) +{ +	unsigned short value; +	unsigned short PhyAnar; +	unsigned short PhyAnalpar; + +	/* Set dm9161 control register */ +	if (!at91rm9200_EmacReadPhy (p_mac, DM9161_BMCR, &value)) +		return FALSE; +	value &= ~DM9161_AUTONEG;	/* remove autonegotiation enable */ +	value |= DM9161_ISOLATE;	/* Electrically isolate PHY */ +	if (!at91rm9200_EmacWritePhy (p_mac, DM9161_BMCR, &value)) +		return FALSE; + +	/* Set the Auto_negotiation Advertisement Register */ +	/* MII advertising for Next page, 100BaseTxFD and HD, 10BaseTFD and HD, IEEE 802.3 */ +	PhyAnar = DM9161_NP | DM9161_TX_FDX | DM9161_TX_HDX | +		  DM9161_10_FDX | DM9161_10_HDX | DM9161_AN_IEEE_802_3; +	if (!at91rm9200_EmacWritePhy (p_mac, DM9161_ANAR, &PhyAnar)) +		return FALSE; + +	/* Read the Control Register     */ +	if (!at91rm9200_EmacReadPhy (p_mac, DM9161_BMCR, &value)) +		return FALSE; + +	value |= DM9161_SPEED_SELECT | DM9161_AUTONEG | DM9161_DUPLEX_MODE; +	if (!at91rm9200_EmacWritePhy (p_mac, DM9161_BMCR, &value)) +		return FALSE; +	/* Restart Auto_negotiation  */ +	value |= DM9161_RESTART_AUTONEG; +	if (!at91rm9200_EmacWritePhy (p_mac, DM9161_BMCR, &value)) +		return FALSE; + +	/*check AutoNegotiate complete */ +	udelay (10000); +	at91rm9200_EmacReadPhy (p_mac, DM9161_BMSR, &value); +	if (!(value & DM9161_AUTONEG_COMP)) +		return FALSE; + +	/* Get the AutoNeg Link partner base page */ +	if (!at91rm9200_EmacReadPhy (p_mac, DM9161_ANLPAR, &PhyAnalpar)) +		return FALSE; + +	if ((PhyAnar & DM9161_TX_FDX) && (PhyAnalpar & DM9161_TX_FDX)) { +		/*set MII for 100BaseTX and Full Duplex  */ +		p_mac->EMAC_CFG |= AT91C_EMAC_SPD | AT91C_EMAC_FD; +		return TRUE; +	} + +	if ((PhyAnar & DM9161_10_FDX) && (PhyAnalpar & DM9161_10_FDX)) { +		/*set MII for 10BaseT and Full Duplex  */ +		p_mac->EMAC_CFG = (p_mac->EMAC_CFG & +				~(AT91C_EMAC_SPD | AT91C_EMAC_FD)) +				| AT91C_EMAC_FD; +		return TRUE; +	} +	return FALSE; +} + + +/* + * Name: + *	at91rm92000_GetPhyInterface + * Description: + *	Initialise the interface functions to the PHY + * Arguments: + *	None + * Return value: + *	None + */ +void at91rm92000_GetPhyInterface(AT91PS_PhyOps p_phyops) +{ +	p_phyops->Init = dm9161_InitPhy; +	p_phyops->IsPhyConnected = dm9161_IsPhyConnected; +	p_phyops->GetLinkSpeed = dm9161_GetLinkSpeed; +	p_phyops->AutoNegotiate = dm9161_AutoNegotiate; +} + +#endif	/* CONFIG_COMMANDS & CFG_CMD_NET */ + +#endif	/* CONFIG_DRIVER_ETHER */ diff --git a/board/cmc_pu2/flash.c b/board/cmc_pu2/flash.c new file mode 100644 index 000000000..5220fcf5d --- /dev/null +++ b/board/cmc_pu2/flash.c @@ -0,0 +1,507 @@ +/* + * (C) Copyright 2002 + * Lineo, Inc. <www.lineo.com> + * Bernhard Kuhn <bkuhn@lineo.com> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.de> + * + * 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 <common.h> + +ulong myflush(void); + + +/* Flash Organization Structure */ +typedef struct OrgDef +{ +	unsigned int sector_number; +	unsigned int sector_size; +} OrgDef; + + +/* Flash Organizations */ +OrgDef OrgAT49BV16x4[] = +{ +	{  8,  8*1024 },	/*   8 *  8 kBytes sectors */ +	{  2, 32*1024 },	/*   2 * 32 kBytes sectors */ +	{ 30, 64*1024 },	/*  30 * 64 kBytes sectors */ +}; + +OrgDef OrgAT49BV16x4A[] = +{ +	{  8,  8*1024 },	/*   8 *  8 kBytes sectors */ +	{ 31, 64*1024 },	/*  31 * 64 kBytes sectors */ +}; + +OrgDef OrgAT49BV6416[] = +{ +	{   8,  8*1024 },	/*   8 *  8 kBytes sectors */ +	{ 127, 64*1024 },	/* 127 * 64 kBytes sectors */ +}; + +flash_info_t    flash_info[CFG_MAX_FLASH_BANKS]; + +/* AT49BV1614A Codes */ +#define FLASH_CODE1		0xAA +#define FLASH_CODE2		0x55 +#define ID_IN_CODE		0x90 +#define ID_OUT_CODE		0xF0 + + +#define CMD_READ_ARRAY		0x00F0 +#define CMD_UNLOCK1		0x00AA +#define CMD_UNLOCK2		0x0055 +#define CMD_ERASE_SETUP		0x0080 +#define CMD_ERASE_CONFIRM	0x0030 +#define CMD_PROGRAM		0x00A0 +#define CMD_UNLOCK_BYPASS	0x0020 +#define CMD_SECTOR_UNLOCK	0x0070 + +#define MEM_FLASH_ADDR1		(*(volatile u16 *)(CFG_FLASH_BASE + (0x00005555<<1))) +#define MEM_FLASH_ADDR2		(*(volatile u16 *)(CFG_FLASH_BASE + (0x00002AAA<<1))) + +#define BIT_ERASE_DONE		0x0080 +#define BIT_RDY_MASK		0x0080 +#define BIT_PROGRAM_ERROR	0x0020 +#define BIT_TIMEOUT		0x80000000 /* our flag */ + +#define READY 1 +#define ERR   2 +#define TMO   4 + +/*----------------------------------------------------------------------- + */ +void flash_identification (flash_info_t * info) +{ +	volatile u16 manuf_code, device_code, add_device_code; + +	MEM_FLASH_ADDR1 = FLASH_CODE1; +	MEM_FLASH_ADDR2 = FLASH_CODE2; +	MEM_FLASH_ADDR1 = ID_IN_CODE; + +	manuf_code = *(volatile u16 *) CFG_FLASH_BASE; +	device_code = *(volatile u16 *) (CFG_FLASH_BASE + 2); +	add_device_code = *(volatile u16 *) (CFG_FLASH_BASE + (3 << 1)); + +	MEM_FLASH_ADDR1 = FLASH_CODE1; +	MEM_FLASH_ADDR2 = FLASH_CODE2; +	MEM_FLASH_ADDR1 = ID_OUT_CODE; + +	/* Vendor type */ +	info->flash_id = ATM_MANUFACT & FLASH_VENDMASK; +	printf ("Atmel: "); + +	if ((device_code & FLASH_TYPEMASK) == (ATM_ID_BV1614 & FLASH_TYPEMASK)) { + +		if ((add_device_code & FLASH_TYPEMASK) == +			(ATM_ID_BV1614A & FLASH_TYPEMASK)) { +			info->flash_id |= ATM_ID_BV1614A & FLASH_TYPEMASK; +			printf ("AT49BV1614A (16Mbit)\n"); +		} else {				/* AT49BV1614 Flash */ +			info->flash_id |= ATM_ID_BV1614 & FLASH_TYPEMASK; +			printf ("AT49BV1614 (16Mbit)\n"); +		} + +	} else if ((device_code & FLASH_TYPEMASK) == (ATM_ID_BV6416 & FLASH_TYPEMASK)) { +		info->flash_id |= ATM_ID_BV6416 & FLASH_TYPEMASK; +		printf ("AT49BV6416 (64Mbit)\n"); +	} +} + +ushort flash_number_sector(OrgDef *pOrgDef, unsigned int nb_blocks) +{ +	int i, nb_sectors = 0; + +	for (i=0; i<nb_blocks; i++){ +		nb_sectors += pOrgDef[i].sector_number; +	} + +	return nb_sectors; +} + +void flash_unlock_sector(flash_info_t * info, unsigned int sector) +{ +	volatile u16 *addr = (volatile u16 *) (info->start[sector]); + +	MEM_FLASH_ADDR1 = CMD_UNLOCK1; +	*addr = CMD_SECTOR_UNLOCK; +} + + +ulong flash_init (void) +{ +	int i, j, k; +	unsigned int flash_nb_blocks, sector; +	unsigned int start_address; +	OrgDef *pOrgDef; + +	ulong size = 0; + +	for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) { +		ulong flashbase = 0; + +		flash_identification (&flash_info[i]); + +		if ((flash_info[i].flash_id & FLASH_TYPEMASK) == +			(ATM_ID_BV1614 & FLASH_TYPEMASK)) { + +			pOrgDef = OrgAT49BV16x4; +			flash_nb_blocks = sizeof (OrgAT49BV16x4) / sizeof (OrgDef); +		} else if ((flash_info[i].flash_id & FLASH_TYPEMASK) == +			(ATM_ID_BV1614A & FLASH_TYPEMASK)){	/* AT49BV1614A Flash */ + +			pOrgDef = OrgAT49BV16x4A; +			flash_nb_blocks = sizeof (OrgAT49BV16x4A) / sizeof (OrgDef); +		} else if ((flash_info[i].flash_id & FLASH_TYPEMASK) == +			(ATM_ID_BV6416 & FLASH_TYPEMASK)){	/* AT49BV6416 Flash */ + +			pOrgDef = OrgAT49BV6416; +			flash_nb_blocks = sizeof (OrgAT49BV6416) / sizeof (OrgDef); +		} else { +			flash_nb_blocks = 0; +			pOrgDef = OrgAT49BV16x4; +		} + +		flash_info[i].sector_count = flash_number_sector(pOrgDef, flash_nb_blocks); +		memset (flash_info[i].protect, 0, flash_info[i].sector_count); + +		if (i == 0) +			flashbase = PHYS_FLASH_1; +		else +			panic ("configured too many flash banks!\n"); + +		sector = 0; +		start_address = flashbase; +		flash_info[i].size = 0; + +		for (j = 0; j < flash_nb_blocks; j++) { +			for (k = 0; k < pOrgDef[j].sector_number; k++) { +				flash_info[i].start[sector++] = start_address; +				start_address += pOrgDef[j].sector_size; +				flash_info[i].size += pOrgDef[j].sector_size; +			} +		} + +		size += flash_info[i].size; + +		if ((flash_info[i].flash_id & FLASH_TYPEMASK) == +			(ATM_ID_BV6416 & FLASH_TYPEMASK)){	/* AT49BV6416 Flash */ + +			/* Unlock all sectors at reset */ +			for (j=0; j<flash_info[i].sector_count; j++){ +				flash_unlock_sector(&flash_info[i], j); +			} +		} +	} + +	/* Protect binary boot image */ +	flash_protect (FLAG_PROTECT_SET, +		       CFG_FLASH_BASE, +		       CFG_FLASH_BASE + CFG_BOOT_SIZE - 1, &flash_info[0]); + +	/* Protect environment variables */ +	flash_protect (FLAG_PROTECT_SET, +		       CFG_ENV_ADDR, +		       CFG_ENV_ADDR + CFG_ENV_SIZE - 1, &flash_info[0]); + +	/* Protect U-Boot gzipped image */ +	flash_protect (FLAG_PROTECT_SET, +		       CFG_U_BOOT_BASE, +		       CFG_U_BOOT_BASE + CFG_U_BOOT_SIZE - 1, &flash_info[0]); + +	return size; +} + +/*----------------------------------------------------------------------- + */ +void flash_print_info (flash_info_t * info) +{ +	int i; + +	switch (info->flash_id & FLASH_VENDMASK) { +	case (ATM_MANUFACT & FLASH_VENDMASK): +		printf ("Atmel: "); +		break; +	default: +		printf ("Unknown Vendor "); +		break; +	} + +	switch (info->flash_id & FLASH_TYPEMASK) { +	case (ATM_ID_BV1614 & FLASH_TYPEMASK): +		printf ("AT49BV1614 (16Mbit)\n"); +		break; +	case (ATM_ID_BV1614A & FLASH_TYPEMASK): +		printf ("AT49BV1614A (16Mbit)\n"); +		break; +	case (ATM_ID_BV6416 & FLASH_TYPEMASK): +		printf ("AT49BV6416 (64Mbit)\n"); +		break; +	default: +		printf ("Unknown Chip Type\n"); +		goto Done; +		break; +	} + +	printf ("  Size: %ld MB in %d Sectors\n", +		info->size >> 20, info->sector_count); + +	printf ("  Sector Start Addresses:"); +	for (i = 0; i < info->sector_count; i++) { +		if ((i % 5) == 0) { +			printf ("\n   "); +		} +		printf (" %08lX%s", info->start[i], +			info->protect[i] ? " (RO)" : "     "); +	} +	printf ("\n"); + +Done:	; +} + +/*----------------------------------------------------------------------- + */ + +int flash_erase (flash_info_t * info, int s_first, int s_last) +{ +	ulong result; +	int iflag, cflag, prot, sect; +	int rc = ERR_OK; +	int chip1; + +	/* first look for protection bits */ + +	if (info->flash_id == FLASH_UNKNOWN) +		return ERR_UNKNOWN_FLASH_TYPE; + +	if ((s_first < 0) || (s_first > s_last)) { +		return ERR_INVAL; +	} + +	if ((info->flash_id & FLASH_VENDMASK) != +		(ATM_MANUFACT & FLASH_VENDMASK)) { +		return ERR_UNKNOWN_FLASH_VENDOR; +	} + +	prot = 0; +	for (sect = s_first; sect <= s_last; ++sect) { +		if (info->protect[sect]) { +			prot++; +		} +	} +	if (prot) +		return ERR_PROTECTED; + +	/* +	 * Disable interrupts which might cause a timeout +	 * here. Remember that our exception vectors are +	 * at address 0 in the flash, and we don't want a +	 * (ticker) exception to happen while the flash +	 * chip is in programming mode. +	 */ +	cflag = icache_status (); +	icache_disable (); +	iflag = disable_interrupts (); + +	/* Start erase on unprotected sectors */ +	for (sect = s_first; sect <= s_last && !ctrlc (); sect++) { +		printf ("Erasing sector %2d ... ", sect); + +		/* arm simple, non interrupt dependent timer */ +		reset_timer_masked (); + +		if (info->protect[sect] == 0) {	/* not protected */ +			volatile u16 *addr = (volatile u16 *) (info->start[sect]); + +			MEM_FLASH_ADDR1 = CMD_UNLOCK1; +			MEM_FLASH_ADDR2 = CMD_UNLOCK2; +			MEM_FLASH_ADDR1 = CMD_ERASE_SETUP; + +			MEM_FLASH_ADDR1 = CMD_UNLOCK1; +			MEM_FLASH_ADDR2 = CMD_UNLOCK2; +			*addr = CMD_ERASE_CONFIRM; + +			/* wait until flash is ready */ +			chip1 = 0; + +			do { +				result = *addr; + +				/* check timeout */ +				if (get_timer_masked () > CFG_FLASH_ERASE_TOUT) { +					MEM_FLASH_ADDR1 = CMD_READ_ARRAY; +					chip1 = TMO; +					break; +				} + +				if (!chip1 && (result & 0xFFFF) & BIT_ERASE_DONE) +					chip1 = READY; + +			} while (!chip1); + +			MEM_FLASH_ADDR1 = CMD_READ_ARRAY; + +			if (chip1 == ERR) { +				rc = ERR_PROG_ERROR; +				goto outahere; +			} +			if (chip1 == TMO) { +				rc = ERR_TIMOUT; +				goto outahere; +			} + +			printf ("ok.\n"); +		} else {			/* it was protected */ +			printf ("protected!\n"); +		} +	} + +	if (ctrlc ()) +		printf ("User Interrupt!\n"); + +outahere: +	/* allow flash to settle - wait 10 ms */ +	udelay_masked (10000); + +	if (iflag) +		enable_interrupts (); + +	if (cflag) +		icache_enable (); + +	return rc; +} + +/*----------------------------------------------------------------------- + * Copy memory to flash + */ + +volatile static int write_word (flash_info_t * info, ulong dest, +								ulong data) +{ +	volatile u16 *addr = (volatile u16 *) dest; +	ulong result; +	int rc = ERR_OK; +	int cflag, iflag; +	int chip1; + +	/* +	 * Check if Flash is (sufficiently) erased +	 */ +	result = *addr; +	if ((result & data) != data) +		return ERR_NOT_ERASED; + + +	/* +	 * Disable interrupts which might cause a timeout +	 * here. Remember that our exception vectors are +	 * at address 0 in the flash, and we don't want a +	 * (ticker) exception to happen while the flash +	 * chip is in programming mode. +	 */ +	cflag = icache_status (); +	icache_disable (); +	iflag = disable_interrupts (); + +	MEM_FLASH_ADDR1 = CMD_UNLOCK1; +	MEM_FLASH_ADDR2 = CMD_UNLOCK2; +	MEM_FLASH_ADDR1 = CMD_PROGRAM; +	*addr = data; + +	/* arm simple, non interrupt dependent timer */ +	reset_timer_masked (); + +	/* wait until flash is ready */ +	chip1 = 0; +	do { +		result = *addr; + +		/* check timeout */ +		if (get_timer_masked () > CFG_FLASH_ERASE_TOUT) { +			chip1 = ERR | TMO; +			break; +		} +		if (!chip1 && ((result & 0x80) == (data & 0x80))) +			chip1 = READY; + +	} while (!chip1); + +	*addr = CMD_READ_ARRAY; + +	if (chip1 == ERR || *addr != data) +		rc = ERR_PROG_ERROR; + +	if (iflag) +		enable_interrupts (); + +	if (cflag) +		icache_enable (); + +	return rc; +} + +/*----------------------------------------------------------------------- + * Copy memory to flash. + */ + +int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt) +{ +	ulong wp, data; +	int rc; + +	if (addr & 1) { +		printf ("unaligned destination not supported\n"); +		return ERR_ALIGN; +	}; + +	if ((int) src & 1) { +		printf ("unaligned source not supported\n"); +		return ERR_ALIGN; +	}; + +	wp = addr; + +	while (cnt >= 2) { +		data = *((volatile u16 *) src); +		if ((rc = write_word (info, wp, data)) != 0) { +			return (rc); +		} +		src += 2; +		wp += 2; +		cnt -= 2; +	} + +	if (cnt == 1) { +		data = (*((volatile u8 *) src)) | (*((volatile u8 *) (wp + 1)) << +										   8); +		if ((rc = write_word (info, wp, data)) != 0) { +			return (rc); +		} +		src += 1; +		wp += 1; +		cnt -= 1; +	}; + +	return ERR_OK; +} diff --git a/board/cmc_pu2/memsetup.S b/board/cmc_pu2/memsetup.S new file mode 100644 index 000000000..168cd6bd8 --- /dev/null +++ b/board/cmc_pu2/memsetup.S @@ -0,0 +1,200 @@ +/* + * Memory Setup stuff - taken from blob memsetup.S + * + * Copyright (C) 1999 2000 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl) and + *                     Jan-Derk Bakker (J.D.Bakker@its.tudelft.nl) + * + * Modified for the at91rm9200dk board by + * (C) Copyright 2004 + * Gary Jennejohn, DENX Software Engineering, <gj@denx.de> + * + * 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 <config.h> +#include <version.h> + +#ifdef CONFIG_BOOTBINFUNC +/* + * some parameters for the board + * + * This is based on rm9200dk.cfg for the BDI2000 from ABATRON which in + * turn is based on the boot.bin code from ATMMEL + * + */ + +/* flash */ +#define MC_PUIA 0xFFFFFF10 +#define MC_PUIA_VAL 0x00000000 +#define MC_PUP 0xFFFFFF50 +#define MC_PUP_VAL 0x00000000 +#define MC_PUER 0xFFFFFF54 +#define MC_PUER_VAL 0x00000000 +#define MC_ASR 0xFFFFFF04 +#define MC_ASR_VAL 0x00000000 +#define MC_AASR 0xFFFFFF08 +#define MC_AASR_VAL 0x00000000 +#define EBI_CFGR 0xFFFFFF64 +#define EBI_CFGR_VAL 0x00000000 +#define SMC2_CSR 0xFFFFFF70 +#define SMC2_CSR_VAL 0x00003284 /* 16bit, 2 TDF, 4 WS */ + +/* clocks */ +#define PLLAR 0xFFFFFC28 +#define PLLAR_VAL 0x20263E04 /* 179.712000 MHz for PCK */ +#define PLLBR 0xFFFFFC2C +#define PLLBR_VAL 0x10483E0E /* 48.054857 MHz (divider by 2 for USB) */ +#define MCKR 0xFFFFFC30 +#define MCKR_VAL 0x00000202 /* PCK/3 = MCK Master Clock = 59.904000MHz from PLLA */ + +/* sdram */ +#define PIOC_ASR 0xFFFFF870 +#define PIOC_ASR_VAL 0xFFFF0000 /* Configure PIOC as peripheral (D16/D31) */ +#define PIOC_BSR 0xFFFFF804 +#define PIOC_BSR_VAL 0x00000000 +#define PIOC_PDR 0xFFFFF804 +#define PIOC_PDR_VAL 0xFFFF0000 +#define EBI_CSA 0xFFFFFF60 +#define EBI_CSA_VAL 0x00000002 /* CS1=SDRAM */ +#define SDRC_CR 0xFFFFFF98 +#define SDRC_CR_VAL 0x2188c155 +#define SDRAM 0x20000000 /* address of the SDRAM */ +#define SDRAM1 0x20000080 /* address of the SDRAM */ +#define SDRAM_VAL 0x00000000 /* value written to SDRAM */ +#define SDRC_MR 0xFFFFFF90 +#define SDRC_MR_VAL 0x00000002 /* Precharge All */ +#define SDRC_MR_VAL1 0x00000004 /* refresh */ +#define SDRC_MR_VAL2 0x00000003 /* Load Mode Register */ +#define SDRC_MR_VAL3 0x00000000 /* Normal Mode */ +#define SDRC_TR 0xFFFFFF94 +#define SDRC_TR_VAL 0x000002E0 /* Write refresh rate */ + + +_TEXT_BASE: +	.word	TEXT_BASE + +.globl memsetup +memsetup: +	/* memory control configuration */ +	/* this isn't very elegant, but  what the heck */ +	ldr     r0, =SMRDATA +	ldr	r1, _TEXT_BASE +	sub	r0, r0, r1 +	add     r2, r0, #80 +0: +	/* the address */ +	ldr     r1, [r0], #4 +	/* the value */ +	ldr     r3, [r0], #4 +	str     r3, [r1] +	cmp     r2, r0 +	bne     0b +	/* delay - this is all done by guess */ +	ldr 	r0, =0x00001000 +1: +	subs    r0, r0, #1               +	bhi     1b +	ldr     r0, =SMRDATA1 +	ldr	r1, _TEXT_BASE +	sub	r0, r0, r1 +	add     r2, r0, #176 +2: +	/* the address */ +	ldr     r1, [r0], #4 +	/* the value */ +	ldr     r3, [r0], #4 +	str     r3, [r1] +	cmp     r2, r0 +	bne     2b + +	/* everything is fine now */ +	mov	pc, lr + +	.ltorg + +SMRDATA: +	.word MC_PUIA +	.word MC_PUIA_VAL +	.word MC_PUP +	.word MC_PUP_VAL +	.word MC_PUER +	.word MC_PUER_VAL +	.word MC_ASR +	.word MC_ASR_VAL +	.word MC_AASR +	.word MC_AASR_VAL +	.word EBI_CFGR +	.word EBI_CFGR_VAL +	.word SMC2_CSR +	.word SMC2_CSR_VAL +	.word PLLAR +	.word PLLAR_VAL +	.word PLLBR +	.word PLLBR_VAL +	.word MCKR +	.word MCKR_VAL +	/* SMRDATA is 80 bytes long */ +	/* here there's a delay of 100 */ +SMRDATA1: +	.word PIOC_ASR +	.word PIOC_ASR_VAL +	.word PIOC_BSR +	.word PIOC_BSR_VAL +	.word PIOC_PDR +	.word PIOC_PDR_VAL +	.word EBI_CSA +	.word EBI_CSA_VAL +	.word SDRC_CR +	.word SDRC_CR_VAL +	.word SDRC_MR +	.word SDRC_MR_VAL +	.word SDRAM +	.word SDRAM_VAL +	.word SDRC_MR +	.word SDRC_MR_VAL1 +	.word SDRAM +	.word SDRAM_VAL +	.word SDRAM +	.word SDRAM_VAL +	.word SDRAM +	.word SDRAM_VAL +	.word SDRAM +	.word SDRAM_VAL +	.word SDRAM +	.word SDRAM_VAL +	.word SDRAM +	.word SDRAM_VAL +	.word SDRAM +	.word SDRAM_VAL +	.word SDRAM +	.word SDRAM_VAL +	.word SDRC_MR +	.word SDRC_MR_VAL2 +	.word SDRAM1 +	.word SDRAM_VAL +	.word SDRC_TR +	.word SDRC_TR_VAL +	.word SDRAM +	.word SDRAM_VAL +	.word SDRC_MR +	.word SDRC_MR_VAL3 +	.word SDRAM +	.word SDRAM_VAL +	/* SMRDATA1 is 176 bytes long */ +#endif /* CONFIG_BOOTBINFUNC */ diff --git a/board/cmc_pu2/u-boot.lds b/board/cmc_pu2/u-boot.lds new file mode 100644 index 000000000..0282898d7 --- /dev/null +++ b/board/cmc_pu2/u-boot.lds @@ -0,0 +1,56 @@ +/* + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <gj@denx.de> + * + * 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 + */ + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +/*OUTPUT_FORMAT("elf32-arm", "elf32-arm", "elf32-arm")*/ +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ +	. = 0x00000000; + +	. = ALIGN(4); +	.text      : +	{ +	  cpu/at91rm9200/start.o	(.text) +	  *(.text) +	} + +	. = ALIGN(4); +	.rodata : { *(.rodata) } + +	. = ALIGN(4); +	.data : { *(.data) } + +	. = ALIGN(4); +	.got : { *(.got) } + +	__u_boot_cmd_start = .; +	.u_boot_cmd : { *(.u_boot_cmd) } +	__u_boot_cmd_end = .; + +	. = ALIGN(4); +	__bss_start = .; +	.bss : { *(.bss) } +	_end = .; +} diff --git a/cpu/at91rm9200/Makefile b/cpu/at91rm9200/Makefile index dfe50c0b0..b7a30c93b 100644 --- a/cpu/at91rm9200/Makefile +++ b/cpu/at91rm9200/Makefile @@ -27,7 +27,7 @@ LIB	= lib$(CPU).a  START	= start.o  OBJS	= serial.o interrupts.o cpu.o \ -	  at91rm9200_ether.o +	  at91rm9200_ether.o i2c.o  all:	.depend $(START) $(LIB) diff --git a/cpu/at91rm9200/cpu.c b/cpu/at91rm9200/cpu.c index c006d9c7e..a7e2ca916 100644 --- a/cpu/at91rm9200/cpu.c +++ b/cpu/at91rm9200/cpu.c @@ -35,8 +35,8 @@  #include <asm/io.h>  #include <asm/arch/hardware.h> -#if !defined(CONFIG_DBGU) && !defined(CONFIG_USART1) -#error must define one of CONFIG_DBGU or CONFIG_USART1 +#if !defined(CONFIG_DBGU) && !defined(CONFIG_USART0) && !defined(CONFIG_USART1) +#error must define one of CONFIG_DBGU or CONFIG_USART0 or CONFIG_USART1  #endif  /* read co-processor 15, register #1 (control register) */ @@ -123,6 +123,9 @@ int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])  #ifdef CONFIG_DBGU     AT91PS_USART us = AT91C_BASE_DBGU;  #endif +#ifdef CONFIG_USART0 +   AT91PS_USART us = AT91C_BASE_US0; +#endif  #ifdef CONFIG_USART1     AT91PS_USART us = AT91C_BASE_US1;  #endif diff --git a/cpu/at91rm9200/i2c.c b/cpu/at91rm9200/i2c.c new file mode 100644 index 000000000..d5d6268db --- /dev/null +++ b/cpu/at91rm9200/i2c.c @@ -0,0 +1,192 @@ +/* + *  i2c Support for Atmel's AT91RM9200 Two-Wire Interface + * + *  (c) Rick Bronson + * + *  Borrowed heavily from original work by: + *  Copyright (c) 2000 Philip Edelbrock <phil@stimpy.netroedge.com> + * + *  Modified to work with u-boot by (C) 2004 Gary Jennejohn garyj@denx.de + * + *  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., 675 Mass Ave, Cambridge, MA 02139, USA. + * +*/ +#include <common.h> + +#ifdef CONFIG_HARD_I2C + +#include <i2c.h> +#include <asm/io.h> +#include <asm/arch/hardware.h> + +#include <at91rm9200_i2c.h> + +static int debug = 0; + +/* + * Poll the i2c status register until the specified bit is set. + * Returns 0 if timed out (100 msec) + */ +static short at91_poll_status(AT91PS_TWI twi, unsigned long bit) { +	int loop_cntr = 10000; +	do { +		udelay(100); +	} while (!(twi->TWI_SR & bit) && (--loop_cntr > 0)); + +	return (loop_cntr > 0); +} + +/* + * Generic i2c master transfer entrypoint + * + * rw == 1 means that this is a read + */ +static int +at91_xfer(unsigned char chip, unsigned int addr, int alen, +						unsigned char *buffer, int len, int rw) +{ +	AT91PS_TWI twi = (AT91PS_TWI) AT91_TWI_BASE; +	int length; +	unsigned char *buf; + +	/* Set the TWI Master Mode Register */ +	twi->TWI_MMR = (chip << 16) | (alen << 8) +		| ((rw == 1) ? AT91C_TWI_MREAD : 0); + +	/* Set TWI Internal Address Register with first messages data field */ +	/* only one address byte is supported  */ +	if (alen > 0) +		twi->TWI_IADR = addr & 0xff; + +	length = len; +	buf = buffer; +	if (length && buf) {	/* sanity check */ +		if (rw) { +			twi->TWI_CR = AT91C_TWI_START; +			while (length--) { +				if (!length) +					twi->TWI_CR = AT91C_TWI_STOP; +				/* Wait until transfer is finished */ +				if (!at91_poll_status(twi, AT91C_TWI_RXRDY)) { +					if (debug) +						printf("at91_i2c: timeout 1\n"); +					return 1; +				} +				*buf++ = twi->TWI_RHR; +			} +			if (!at91_poll_status(twi, AT91C_TWI_TXCOMP)) { +				if (debug) +					printf("at91_i2c: timeout 2\n"); +				return 1; +			} +		} else { +			twi->TWI_CR = AT91C_TWI_START; +			while (length--) { +				twi->TWI_THR = *buf++; +				if (!length) +					twi->TWI_CR = AT91C_TWI_STOP; +				if (!at91_poll_status(twi, AT91C_TWI_TXRDY)) { +					if (debug) +						printf("at91_i2c: timeout 3\n"); +					return 1; +				} +			} +			/* Wait until transfer is finished */ +			if (!at91_poll_status(twi, AT91C_TWI_TXCOMP)) { +				if (debug) +					printf("at91_i2c: timeout 4\n"); +				return 1; +			} +		} +	} +	return 0; +} + +int +i2c_probe(unsigned char chip) +{ +	char buffer[1]; + +	return at91_xfer(chip, 0, 0, buffer, 1, 1); +} + +int +i2c_read(unsigned char chip, unsigned int addr, int alen, +							unsigned char *buffer, int len) +{ +	/* we only allow one address byte */ +	if (alen > 1) +		return 1; +#ifdef CFG_I2C_EEPROM_ADDR_OVERFLOW +	/* XXX assume an ATMEL AT24C16 */ +	if (alen == 1) { +		chip |= (addr >> 8) & 0xff; +		addr = addr & 0xff; +	} +#endif +	return at91_xfer(chip, addr, alen, buffer, len, 1); +} + +int +i2c_write(unsigned char chip, unsigned int addr, int alen, +							unsigned char *buffer, int len) +{ +	int i; +	unsigned char *buf; + +	/* we only allow one address byte */ +	if (alen > 1) +		return 1; +#ifdef CFG_I2C_EEPROM_ADDR_OVERFLOW +	/* XXX assume an ATMEL AT24C16 */ +	if (alen == 1) { +		buf = buffer; +		/* do single byte writes */ +		for (i = 0; i < len; i++) { +			chip |= (addr >> 8) & 0xff; +			addr = addr & 0xff; +			if (at91_xfer(chip, addr, alen, buf++, 1, 0)) +				return 1; +		} +	} +	return 0; +#endif +	return at91_xfer(chip, addr, alen, buffer, len, 0); +} + +/* + * Main initialization routine + */ +void +i2c_init(int speed, int slaveaddr) +{ +	AT91PS_TWI twi = (AT91PS_TWI) AT91_TWI_BASE; + +	*AT91C_PIOA_PDR = AT91C_PA25_TWD | AT91C_PA26_TWCK; +	*AT91C_PIOA_ASR = AT91C_PA25_TWD | AT91C_PA26_TWCK; +	*AT91C_PIOA_MDER = AT91C_PA25_TWD | AT91C_PA26_TWCK; +	*AT91C_PMC_PCER = 1 << AT91C_ID_TWI;		/* enable peripheral clock */ + +	twi->TWI_IDR = 0x3ff;				/* Disable all interrupts */ +	twi->TWI_CR = AT91C_TWI_SWRST;			/* Reset peripheral */ +	twi->TWI_CR = AT91C_TWI_MSEN | AT91C_TWI_SVDIS;	/* Set Master mode */ + +	/* Here, CKDIV = 1 and CHDIV=CLDIV  ==> CLDIV = CHDIV = 1/4*((Fmclk/FTWI) -6) */ +	twi->TWI_CWGR = AT91C_TWI_CKDIV1 | AT91C_TWI_CLDIV3 | (AT91C_TWI_CLDIV3 << 8); + +	printf("Found AT91 i2c\n"); +	return; +} +#endif /* CONFIG_HARD_I2C */ diff --git a/cpu/at91rm9200/serial.c b/cpu/at91rm9200/serial.c index c16c9d4f0..fb038510c 100644 --- a/cpu/at91rm9200/serial.c +++ b/cpu/at91rm9200/serial.c @@ -33,14 +33,17 @@  #include <asm/io.h>  #include <asm/arch/hardware.h> -#if !defined(CONFIG_DBGU) && !defined(CONFIG_USART1) -#error must define one of CONFIG_DBGU or CONFIG_USART1 +#if !defined(CONFIG_DBGU) && !defined(CONFIG_USART0) && !defined(CONFIG_USART1) +#error must define one of CONFIG_DBGU or CONFIG_USART0 or CONFIG_USART1  #endif  /* ggi thunder */  #ifdef CONFIG_DBGU  AT91PS_USART us = (AT91PS_USART) AT91C_BASE_DBGU;  #endif +#ifdef CONFIG_USART0 +AT91PS_USART us = (AT91PS_USART) AT91C_BASE_US0; +#endif  #ifdef CONFIG_USART1  AT91PS_USART us = (AT91PS_USART) AT91C_BASE_US1;  #endif @@ -50,9 +53,19 @@ void serial_setbrg (void)  	DECLARE_GLOBAL_DATA_PTR;  	int baudrate; -	if ((baudrate = gd->bd->bi_baudrate) <= 0) +	if ((baudrate = gd->baudrate) <= 0)  		baudrate = CONFIG_BAUDRATE; -	us->US_BRGR = CFG_AT91C_BRGR_DIVISOR;	/* hardcode so no __divsi3 */ +	if (baudrate == CONFIG_BAUDRATE) { +		us->US_BRGR = CFG_AT91C_BRGR_DIVISOR;	/* hardcode so no __divsi3 */ +	} else { +#if 0 +		/* 33 -> 115200 */ +		us->US_BRGR = 33 * (115200/baudrate); +#else +		/* MASTER_CLOCK/(16 * baudrate) */ +		us->US_BRGR = (AT91C_MASTER_CLOCK >> 4)/baudrate; +#endif +	}  }  int serial_init (void) @@ -62,6 +75,10 @@ int serial_init (void)  	*AT91C_PIOA_PDR = AT91C_PA31_DTXD | AT91C_PA30_DRXD;	/* PA 31 & 30 */  	*AT91C_PMC_PCER = 1 << AT91C_ID_SYS;	/* enable clock */  #endif +#ifdef CONFIG_USART0 +	*AT91C_PIOA_PDR = AT91C_PA17_TXD0 | AT91C_PA18_RXD0; +	*AT91C_PMC_PCER |= 1 << AT91C_ID_USART0;	/* enable clock */ +#endif  #ifdef CONFIG_USART1  	*AT91C_PIOB_PDR = AT91C_PB21_TXD1 | AT91C_PB20_RXD1;  	*AT91C_PMC_PCER |= 1 << AT91C_ID_USART1;	/* enable clock */ diff --git a/include/asm-arm/arch-at91rm9200/AT91RM9200.h b/include/asm-arm/arch-at91rm9200/AT91RM9200.h index 463f46264..869c4e20b 100644 --- a/include/asm-arm/arch-at91rm9200/AT91RM9200.h +++ b/include/asm-arm/arch-at91rm9200/AT91RM9200.h @@ -446,7 +446,35 @@ typedef struct _AT91S_PDC {  /* ========== Register definition ==================================== */  #define AT91C_SPI_CSR   ((AT91_REG *) 	0xFFFE0030) /* (SPI) Chip Select Register */  #define AT91C_PMC_PCER  ((AT91_REG *) 	0xFFFFFC10) /* (PMC) Peripheral Clock Enable Register */ +#define AT91C_PIOA_PER  ((AT91_REG *) 	0xFFFFF400) /* (PIOA) PIO Enable Register */  #define AT91C_PIOA_PDR  ((AT91_REG *) 	0xFFFFF404) /* (PIOA) PIO Disable Register */ +#define AT91C_PIOA_PSR  ((AT91_REG *) 	0xFFFFF408) /* (PIOA) PIO Status Register */ +#define AT91C_PIOA_OER  ((AT91_REG *) 	0xFFFFF410) /* (PIOA) PIO Output Enable Register */ +#define AT91C_PIOA_ODR  ((AT91_REG *) 	0xFFFFF414) /* (PIOA) PIO Output Disable Register */ +#define AT91C_PIOA_OSR  ((AT91_REG *) 	0xFFFFF418) /* (PIOA) PIO Output Status Register */ +#define AT91C_PIOA_IFER  ((AT91_REG *) 	0xFFFFF420) /* (PIOA) PIO Glitch Input Filter Enable Register */ +#define AT91C_PIOA_IFDR  ((AT91_REG *) 	0xFFFFF424) /* (PIOA) PIO Glitch Input Filter Disable Register */ +#define AT91C_PIOA_IFSR  ((AT91_REG *) 	0xFFFFF428) /* (PIOA) PIO Glitch Input Filter Status Register */ +#define AT91C_PIOA_SODR  ((AT91_REG *) 	0xFFFFF430) /* (PIOA) PIO Set Output Data Register */ +#define AT91C_PIOA_CODR  ((AT91_REG *) 	0xFFFFF434) /* (PIOA) PIO Clear Output Data Register */ +#define AT91C_PIOA_ODSR  ((AT91_REG *) 	0xFFFFF438) /* (PIOA) PIO Output Data Status Register */ +#define AT91C_PIOA_PDSR  ((AT91_REG *) 	0xFFFFF43C) /* (PIOA) PIO Pin Data Status Register */ +#define AT91C_PIOA_IER  ((AT91_REG *) 	0xFFFFF440) /* (PIOA) PIO Interrupt Enable Register */ +#define AT91C_PIOA_IDR  ((AT91_REG *) 	0xFFFFF444) /* (PIOA) PIO Interrupt Disable Register */ +#define AT91C_PIOA_IMR  ((AT91_REG *) 	0xFFFFF448) /* (PIOA) PIO Interrupt Mask Register */ +#define AT91C_PIOA_ISR  ((AT91_REG *) 	0xFFFFF44C) /* (PIOA) PIO Interrupt Status Register */ +#define AT91C_PIOA_MDER  ((AT91_REG *) 	0xFFFFF450) /* (PIOA) PIO Multi-drive Enable Register */ +#define AT91C_PIOA_MDDR  ((AT91_REG *) 	0xFFFFF454) /* (PIOA) PIO Multi-drive Disable Register */ +#define AT91C_PIOA_MDSR  ((AT91_REG *) 	0xFFFFF458) /* (PIOA) PIO Multi-drive Status Register */ +#define AT91C_PIOA_PUDR  ((AT91_REG *) 	0xFFFFF460) /* (PIOA) PIO Pull-up Disable Register */ +#define AT91C_PIOA_PUER  ((AT91_REG *) 	0xFFFFF464) /* (PIOA) PIO Pull-up Enable Register */ +#define AT91C_PIOA_PUSR  ((AT91_REG *) 	0xFFFFF468) /* (PIOA) PIO Pull-up Status Register */ +#define AT91C_PIOA_ASR  ((AT91_REG *) 	0xFFFFF470) /* (PIOA) PIO Peripheral A Select Register */ +#define AT91C_PIOA_BSR  ((AT91_REG *) 	0xFFFFF474) /* (PIOA) PIO Peripheral B Select Register */ +#define AT91C_PIOA_ABSR  ((AT91_REG *) 	0xFFFFF478) /* (PIOA) PIO Peripheral AB Select Register */ +#define AT91C_PIOA_OWER  ((AT91_REG *) 	0xFFFFF4A0) /* (PIOA) PIO Output Write Enable Register */ +#define AT91C_PIOA_OWDR  ((AT91_REG *) 	0xFFFFF4A4) /* (PIOA) PIO Output Write Disable Register */ +#define AT91C_PIOA_OWSR  ((AT91_REG *) 	0xFFFFF4A8) /* (PIOA) PIO Output Write Status Register */  #define AT91C_PIOB_PDR  ((AT91_REG *) 	0xFFFFF604) /* (PIOB) PIO Disable Register */  #define AT91C_PIO_PA30       ((unsigned int) 1 << 30) /* Pin Controlled by PA30 */ @@ -454,19 +482,28 @@ typedef struct _AT91S_PDC {  #define AT91C_PC0_BFCK     ((unsigned int) AT91C_PIO_PC0) /*  Burst Flash Clock */  #define AT91C_PA30_DRXD     ((unsigned int) AT91C_PIO_PA30) /*  DBGU Debug Receive Data */  #define AT91C_PIO_PA31       ((unsigned int) 1 << 31) /* Pin Controlled by PA31 */ +#define AT91C_PA25_TWD		((unsigned int) 1 << 25) +#define AT91C_PA26_TWCK		((unsigned int) 1 << 26)  #define AT91C_PA31_DTXD     ((unsigned int) AT91C_PIO_PA31) /*  DBGU Debug Transmit Data */ +#define AT91C_PIO_PA17       ((unsigned int) 1 << 17) /* Pin Controlled by PA17 */ +#define AT91C_PA17_TXD0     AT91C_PIO_PA17 /*  USART0 Transmit Data */ +#define AT91C_PIO_PA18       ((unsigned int) 1 << 18) /* Pin Controlled by PA18 */ +#define AT91C_PA18_RXD0     AT91C_PIO_PA18 /*  USART0 Receive Data */  #define AT91C_PIO_PB20       ((unsigned int) 1 << 20) /* Pin Controlled by PB20 */ -#define AT91C_PB20_RXD1     ((unsigned int) AT91C_PIO_PB20) /*  USART1 Receive Data */ +#define AT91C_PB20_RXD1     AT91C_PIO_PB20 /*  USART1 Receive Data */  #define AT91C_PIO_PB21       ((unsigned int) 1 << 21) /* Pin Controlled by PB21 */ -#define AT91C_PB21_TXD1     ((unsigned int) AT91C_PIO_PB21) /*  USART1 Transmit Data */ +#define AT91C_PB21_TXD1     AT91C_PIO_PB21 /*  USART1 Transmit Data */ -#define AT91C_ID_SYS    ((unsigned int)  1) /* System Peripheral */ +#define AT91C_ID_SYS    ((unsigned int) 1) /* System Peripheral */ +#define AT91C_ID_PIOA	((unsigned int) 2)	/* PIO port A */ +#define AT91C_ID_PIOB	((unsigned int) 3)	/* PIO port B */ +#define AT91C_ID_PIOC	((unsigned int) 4)	/* PIO port C */ +#define AT91C_ID_USART0	((unsigned int) 6)	/* USART 0 */ +#define AT91C_ID_USART1	((unsigned int) 7)	/* USART 1 */ +#define AT91C_ID_TWI    ((unsigned int) 12) /* Two Wire Interface */ +#define AT91C_ID_SPI    ((unsigned int) 13) /* Serial Peripheral Interface */  #define AT91C_ID_TC0    ((unsigned int) 17) /* Timer Counter 0 */  #define AT91C_ID_EMAC   ((unsigned int) 24) /* Ethernet MAC */ -#define AT91C_ID_SPI    ((unsigned int) 13) /* Serial Peripheral Interface */ -#define AT91C_ID_PIOB	((unsigned int) 3) -#define AT91C_ID_PIOC	((unsigned int) 4) -#define AT91C_ID_USART1	((unsigned int) 7)  #define AT91C_PIO_PC1        ((unsigned int) 1 <<  1) /* Pin Controlled by PC1 */  #define AT91C_PC1_BFRDY_SMOE ((unsigned int) AT91C_PIO_PC1) /*  Burst Flash Ready */ @@ -561,11 +598,14 @@ typedef struct _AT91S_PDC {  #define AT91C_BASE_EMAC      ((AT91PS_EMAC) 	0xFFFBC000) /* (EMAC) Base Address */  #define AT91C_BASE_PMC       ((AT91PS_PMC) 	0xFFFFFC00) /* (PMC) Base Address */  #define AT91C_BASE_TC0       ((AT91PS_TC) 	0xFFFA0000) /* (TC0) Base Address */ -#define AT91C_BASE_DBGU      ((AT91PS_DBGU) 	0xFFFFF200) /* (DBGU) Base Address */ +#define AT91C_BASE_DBGU      ((AT91PS_DBGU)	0xFFFFF200) /* (DBGU) Base Address */ +#define AT91C_BASE_CKGR      ((AT91PS_CKGR) 0xFFFFFC20) /* (CKGR) Base Address */ +#define AT91C_BASE_PIOC      ((AT91PS_PIO) 	0xFFFFF800) /* (PIOC) Base Address */  #define AT91C_BASE_PIOB      ((AT91PS_PIO) 	0xFFFFF600) /* (PIOB) Base Address */  #define AT91C_BASE_PIOA      ((AT91PS_PIO) 	0xFFFFF400) /* (PIOA) Base Address */  #define AT91C_EBI_CSA   ((AT91_REG *) 	0xFFFFFF60) /* (EBI) Chip Select Assignment Register */  #define AT91C_BASE_SMC2      ((AT91PS_SMC2) 	0xFFFFFF70) /* (SMC2) Base Address */ +#define AT91C_BASE_US0       ((AT91PS_USART) 	0xFFFC0000) /* (US0) Base Address */  #define AT91C_BASE_US1       ((AT91PS_USART) 	0xFFFC4000) /* (US1) Base Address */  #define AT91C_TCB0_BMR  ((AT91_REG *) 	0xFFFA00C4) /* (TCB0) TC Block Mode Register */  #define AT91C_TCB0_BCR  ((AT91_REG *) 	0xFFFA00C0) /* (TCB0) TC Block Control Register */ diff --git a/include/at91rm9200_i2c.h b/include/at91rm9200_i2c.h new file mode 100644 index 000000000..cb13d9d4d --- /dev/null +++ b/include/at91rm9200_i2c.h @@ -0,0 +1,126 @@ +// ---------------------------------------------------------------------------- +//          ATMEL Microcontroller Software Support  -  ROUSSET  - +// ---------------------------------------------------------------------------- +//  The software is delivered "AS IS" without warranty or condition of any +//  kind, either express, implied or statutory. This includes without +//  limitation any warranty or condition with respect to merchantability or +//  fitness for any particular purpose, or against the infringements of +//  intellectual property rights of others. +// ---------------------------------------------------------------------------- +// File Name           : at91rm9200_i2c.h +// Object              : AT91RM9200 / TWI definitions +// Generated           : AT91 SW Application Group  12/03/2002 (10:48:02) +// +// ---------------------------------------------------------------------------- + +#ifndef AT91RM9200_TWI_H +#define AT91RM9200_TWI_H + +// ***************************************************************************** +//              SOFTWARE API DEFINITION  FOR Two-wire Interface +// ***************************************************************************** +#ifndef __ASSEMBLY__ + +typedef struct _AT91S_TWI { +	AT91_REG	 TWI_CR; 	// Control Register +	AT91_REG	 TWI_MMR; 	// Master Mode Register +	AT91_REG	 TWI_SMR; 	// Slave Mode Register +	AT91_REG	 TWI_IADR; 	// Internal Address Register +	AT91_REG	 TWI_CWGR; 	// Clock Waveform Generator Register +	AT91_REG	 Reserved0[3]; 	// +	AT91_REG	 TWI_SR; 	// Status Register +	AT91_REG	 TWI_IER; 	// Interrupt Enable Register +	AT91_REG	 TWI_IDR; 	// Interrupt Disable Register +	AT91_REG	 TWI_IMR; 	// Interrupt Mask Register +	AT91_REG	 TWI_RHR; 	// Receive Holding Register +	AT91_REG	 TWI_THR; 	// Transmit Holding Register +	AT91_REG	 Reserved1[50]; 	// +	AT91_REG	 TWI_RPR; 	// Receive Pointer Register +	AT91_REG	 TWI_RCR; 	// Receive Counter Register +	AT91_REG	 TWI_TPR; 	// Transmit Pointer Register +	AT91_REG	 TWI_TCR; 	// Transmit Counter Register +	AT91_REG	 TWI_RNPR; 	// Receive Next Pointer Register +	AT91_REG	 TWI_RNCR; 	// Receive Next Counter Register +	AT91_REG	 TWI_TNPR; 	// Transmit Next Pointer Register +	AT91_REG	 TWI_TNCR; 	// Transmit Next Counter Register +	AT91_REG	 TWI_PTCR; 	// PDC Transfer Control Register +	AT91_REG	 TWI_PTSR; 	// PDC Transfer Status Register +} AT91S_TWI, *AT91PS_TWI; + +#endif + +// -------- TWI_CR : (TWI Offset: 0x0) TWI Control Register -------- +#define AT91C_TWI_START       ( 0x1 <<  0) // (TWI) Send a START Condition +#define AT91C_TWI_STOP        ( 0x1 <<  1) // (TWI) Send a STOP Condition +#define AT91C_TWI_MSEN        ( 0x1 <<  2) // (TWI) TWI Master Transfer Enabled +#define AT91C_TWI_MSDIS       ( 0x1 <<  3) // (TWI) TWI Master Transfer Disabled +#define AT91C_TWI_SVEN        ( 0x1 <<  4) // (TWI) TWI Slave Transfer Enabled +#define AT91C_TWI_SVDIS       ( 0x1 <<  5) // (TWI) TWI Slave Transfer Disabled +#define AT91C_TWI_SWRST       ( 0x1 <<  7) // (TWI) Software Reset +// -------- TWI_MMR : (TWI Offset: 0x4) TWI Master Mode Register -------- +#define AT91C_TWI_IADRSZ      ( 0x3 <<  8) // (TWI) Internal Device Address Size +#define 	AT91C_TWI_IADRSZ_NO                   ( 0x0 <<  8) // (TWI) No internal device address +#define 	AT91C_TWI_IADRSZ_1_BYTE               ( 0x1 <<  8) // (TWI) One-byte internal device address +#define 	AT91C_TWI_IADRSZ_2_BYTE               ( 0x2 <<  8) // (TWI) Two-byte internal device address +#define 	AT91C_TWI_IADRSZ_3_BYTE               ( 0x3 <<  8) // (TWI) Three-byte internal device address +#define AT91C_TWI_MREAD       ( 0x1 << 12) // (TWI) Master Read Direction +#define AT91C_TWI_DADR        ( 0x7F <<  6) // (TWI) Device Address +// -------- TWI_SMR : (TWI Offset: 0x8) TWI Slave Mode Register -------- +#define AT91C_TWI_SADR        ( 0x7F << 16) // (TWI) Slave Device Address +// -------- TWI_CWGR : (TWI Offset: 0x10) TWI Clock Waveform Generator Register -------- +#define AT91C_TWI_CLDIV       ( 0xFF <<  0) // (TWI) Clock Low Divider +#define AT91C_TWI_CHDIV       ( 0xFF <<  8) // (TWI) Clock High Divider +#define AT91C_TWI_CKDIV       ( 0x7 << 16) // (TWI) Clock Divider +// -------- TWI_SR : (TWI Offset: 0x20) TWI Status Register -------- +#define AT91C_TWI_TXCOMP      ( 0x1 <<  0) // (TWI) Transmission Completed +#define AT91C_TWI_RXRDY       ( 0x1 <<  1) // (TWI) Receive holding register ReaDY +#define AT91C_TWI_TXRDY       ( 0x1 <<  2) // (TWI) Transmit holding register ReaDY +#define AT91C_TWI_SVREAD      ( 0x1 <<  3) // (TWI) Slave Read +#define AT91C_TWI_SVACC       ( 0x1 <<  4) // (TWI) Slave Access +#define AT91C_TWI_GCACC       ( 0x1 <<  5) // (TWI) General Call Access +#define AT91C_TWI_OVRE        ( 0x1 <<  6) // (TWI) Overrun Error +#define AT91C_TWI_UNRE        ( 0x1 <<  7) // (TWI) Underrun Error +#define AT91C_TWI_NACK        ( 0x1 <<  8) // (TWI) Not Acknowledged +#define AT91C_TWI_ARBLST      ( 0x1 <<  9) // (TWI) Arbitration Lost +// -------- TWI_IER : (TWI Offset: 0x24) TWI Interrupt Enable Register -------- +// -------- TWI_IDR : (TWI Offset: 0x28) TWI Interrupt Disable Register -------- +// -------- TWI_IMR : (TWI Offset: 0x2c) TWI Interrupt Mask Register -------- + +/* +    i2c Support for Atmel's AT91RM9200 Two-Wire Interface + +    (c) Rick Bronson + +    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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef AT91_I2C_H +#define AT91_I2C_H + +#define AT91C_TWI_CLOCK		100000 +#define AT91C_TWI_SCLOCK	(10 * AT91C_MASTER_CLOCK / AT91C_TWI_CLOCK) +#define AT91C_TWI_CKDIV1	(2 << 16)	/* TWI clock divider.  NOTE: see Errata #22 */ + +#if (AT91C_TWI_SCLOCK % 10) >= 5 +#define AT91C_TWI_CLDIV2 ((AT91C_TWI_SCLOCK / 10) - 5) +#else +#define AT91C_TWI_CLDIV2 ((AT91C_TWI_SCLOCK / 10) - 6) +#endif +#define AT91C_TWI_CLDIV3 ((AT91C_TWI_CLDIV2 + (4 - AT91C_TWI_CLDIV2 % 4)) >> 2) + +#define AT91C_EEPROM_I2C_ADDRESS        (0x50 << 16) + +#endif +#endif diff --git a/include/configs/cmc_pu2.h b/include/configs/cmc_pu2.h new file mode 100644 index 000000000..03f5dde8e --- /dev/null +++ b/include/configs/cmc_pu2.h @@ -0,0 +1,225 @@ +/* + * Rick Bronson <rick@efn.org> + * + * Configuation settings for the AT91RM9200DK board. + * + * 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 + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +/* + * If we are developing, we might want to start armboot from ram + * so we MUST NOT initialize critical regs like mem-timing ... + */ +#define CONFIG_INIT_CRITICAL		/* undef for developing */ + +/* ARM asynchronous clock */ +#define AT91C_MAIN_CLOCK	179712000	/* from 18.432 MHz crystal (18432000 / 4 * 39) */ +#define AT91C_MASTER_CLOCK	59904000	/* peripheral clock (AT91C_MASTER_CLOCK / 3) */ +/* #define AT91C_MASTER_CLOCK	44928000 */	/* peripheral clock (AT91C_MASTER_CLOCK / 4) */ + +#define AT91_SLOW_CLOCK		32768	/* slow clock */ + +#define CONFIG_AT91RM9200DK	1	/* on an AT91RM9200DK Board	 */ +#define CONFIG_CMC_PU2	1		/* on an CMC_PU2 Board	 */ +#undef CONFIG_USE_IRQ			/* we don't need IRQ/FIQ stuff */ +#define CONFIG_CMDLINE_TAG	1	/* enable passing of ATAGs	*/ +#define CONFIG_SETUP_MEMORY_TAGS 1 +#define CONFIG_INITRD_TAG	1 + +/* define this to include the functionality of boot.bin in u-boot */ +#undef CONFIG_BOOTBINFUNC + +/* + * Size of malloc() pool + */ +#define CFG_MALLOC_LEN	(CFG_ENV_SIZE + 128*1024) +#define CFG_GBL_DATA_SIZE	128	/* size in bytes reserved for initial data */ + +#define CONFIG_BAUDRATE 9600 + +#define CFG_AT91C_BRGR_DIVISOR	390	/* hardcode so no __divsi3 : AT91C_MASTER_CLOCK /(baudrate * 16) */ + +/* + * Hardware drivers + */ + +/* define one of these to choose the DBGU, USART0  or USART1 as console */ +#undef CONFIG_DBGU +#undef CONFIG_USART0 +#define CONFIG_USART1 + +#undef	CONFIG_HWFLOW			/* don't include RTS/CTS flow control support	*/ + +#undef	CONFIG_MODEM_SUPPORT		/* disable modem initialization stuff */ + +#define CONFIG_HARD_I2C + +#ifdef CONFIG_HARD_I2C +#define CFG_I2C_SPEED 0 /* not used */ +#define CFG_I2C_SLAVE 0 /* not used */ +#define CONFIG_RTC_RS5C372A	/* RICOH I2C RTC */ +#define CFG_I2C_RTC_ADDR 0x32 +#define CFG_I2C_EEPROM_ADDR 0x50 +#define CFG_I2C_EEPROM_ADDR_LEN 1 +#define CFG_I2C_EEPROM_ADDR_OVERFLOW +#endif + +#define CONFIG_BOOTDELAY      3 +/* #define CONFIG_ENV_OVERWRITE	1 */ + +#ifdef CONFIG_HARD_I2C +#define CONFIG_COMMANDS		\ +		       ((CONFIG_CMD_DFL | \ +			CFG_CMD_I2C | \ +			CFG_CMD_EEPROM | \ +			CFG_CMD_DHCP ) & \ +		      ~(CFG_CMD_BDI | \ +			CFG_CMD_IMI | \ +			CFG_CMD_AUTOSCRIPT | \ +			CFG_CMD_FPGA | \ +			CFG_CMD_MISC | \ +			CFG_CMD_LOADS )) +#else +#define CONFIG_COMMANDS		\ +		       ((CONFIG_CMD_DFL | \ +			CFG_CMD_DHCP ) & \ +		      ~(CFG_CMD_BDI | \ +			CFG_CMD_IMI | \ +			CFG_CMD_AUTOSCRIPT | \ +			CFG_CMD_FPGA | \ +			CFG_CMD_MISC | \ +			CFG_CMD_LOADS )) +#endif + +/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */ +#include <cmd_confdefs.h> + +#define CFG_MAX_NAND_DEVICE	1	/* Max number of NAND devices		*/ +#define SECTORSIZE 512 + +#define ADDR_COLUMN 1 +#define ADDR_PAGE 2 +#define ADDR_COLUMN_PAGE 3 + +#define NAND_ChipID_UNKNOWN	0x00 +#define NAND_MAX_FLOORS 1 +#define NAND_MAX_CHIPS 1 + +#define AT91_SMART_MEDIA_ALE (1 << 22)	/* our ALE is AD22 */ +#define AT91_SMART_MEDIA_CLE (1 << 21)	/* our CLE is AD21 */ + +#define NAND_DISABLE_CE(nand) do { *AT91C_PIOC_SODR = AT91C_PIO_PC0;} while(0) +#define NAND_ENABLE_CE(nand) do { *AT91C_PIOC_CODR = AT91C_PIO_PC0;} while(0) + +#define NAND_WAIT_READY(nand) while (!(*AT91C_PIOC_PDSR & AT91C_PIO_PC2)) + +#define WRITE_NAND_COMMAND(d, adr) do{ *(volatile __u8 *)((unsigned long)adr | AT91_SMART_MEDIA_CLE) = (__u8)(d); } while(0) +#define WRITE_NAND_ADDRESS(d, adr) do{ *(volatile __u8 *)((unsigned long)adr | AT91_SMART_MEDIA_ALE) = (__u8)(d); } while(0) +#define WRITE_NAND(d, adr) do{ *(volatile __u8 *)((unsigned long)adr) = (__u8)d; } while(0) +#define READ_NAND(adr) ((volatile unsigned char)(*(volatile __u8 *)(unsigned long)adr)) +/* the following are NOP's in our implementation */ +#define NAND_CTL_CLRALE(nandptr) +#define NAND_CTL_SETALE(nandptr) +#define NAND_CTL_CLRCLE(nandptr) +#define NAND_CTL_SETCLE(nandptr) + +#define CONFIG_NR_DRAM_BANKS 1 +#define PHYS_SDRAM 0x20000000 +#define PHYS_SDRAM_SIZE 0x2000000  /* 32 megs */ + +#define CFG_MEMTEST_START		PHYS_SDRAM +#define CFG_MEMTEST_END			CFG_MEMTEST_START + PHYS_SDRAM_SIZE - 262144 + +#define CONFIG_DRIVER_ETHER +#define CONFIG_NET_RETRY_COUNT		20 +#define CONFIG_AT91C_USE_RMII + +#define CONFIG_HAS_DATAFLASH		1 +#define CFG_SPI_WRITE_TOUT		(5*CFG_HZ) +#define CFG_MAX_DATAFLASH_BANKS 	2 +#define CFG_MAX_DATAFLASH_PAGES 	16384 +#define CFG_DATAFLASH_LOGIC_ADDR_CS0	0xC0000000	/* Logical adress for CS0 */ +#define CFG_DATAFLASH_LOGIC_ADDR_CS3	0xD0000000	/* Logical adress for CS3 */ + +#define PHYS_FLASH_1			0x10000000 +#define PHYS_FLASH_SIZE			0x200000  /* 2 megs main flash */ +#define CFG_FLASH_BASE			PHYS_FLASH_1 +#define CFG_MAX_FLASH_BANKS		1 +#define CFG_MAX_FLASH_SECT		256 +#define CFG_FLASH_ERASE_TOUT		(2*CFG_HZ) /* Timeout for Flash Erase */ +#define CFG_FLASH_WRITE_TOUT		(2*CFG_HZ) /* Timeout for Flash Write */ + +#undef	CFG_ENV_IS_IN_DATAFLASH + +#ifdef CFG_ENV_IS_IN_DATAFLASH +#define CFG_ENV_OFFSET			0x20000 +#define CFG_ENV_ADDR			(CFG_DATAFLASH_LOGIC_ADDR_CS0 + CFG_ENV_OFFSET) +#define CFG_ENV_SIZE			0x2000  /* 0x8000 */ +#else +#define CFG_ENV_IS_IN_FLASH		1 +#define CFG_ENV_ADDR			(PHYS_FLASH_1 + 0xe000)  /* 0x10000 */ +#define CFG_ENV_SIZE			0x2000  /* 0x8000 */ +#endif + + +#define CFG_LOAD_ADDR		0x21000000  /* default load address */ + +#define CFG_BOOT_SIZE		0x6000 /* 24 KBytes */ +#define CFG_U_BOOT_BASE		(PHYS_FLASH_1 + 0x10000) +#define CFG_U_BOOT_SIZE		0x10000 /* 64 KBytes */ + +#define CFG_BAUDRATE_TABLE	{115200 , 19200, 38400, 57600, 9600 } + +#define CFG_PROMPT		"U-Boot> "	/* Monitor Command Prompt */ +#define CFG_CBSIZE		256		/* Console I/O Buffer Size */ +#define CFG_MAXARGS		16		/* max number of command args */ +#define CFG_PBSIZE		(CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */ + +#ifndef __ASSEMBLY__ +/*----------------------------------------------------------------------- + * Board specific extension for bd_info + * + * This structure is embedded in the global bd_info (bd_t) structure + * and can be used by the board specific code (eg board/...) + */ + +struct bd_info_ext { +	/* helper variable for board environment handling +	 * +	 * env_crc_valid == 0    =>   uninitialised +	 * env_crc_valid  > 0    =>   environment crc in flash is valid +	 * env_crc_valid  < 0    =>   environment crc in flash is invalid +	 */ +	int env_crc_valid; +}; +#endif + +#define CFG_HZ AT91C_MASTER_CLOCK/2	/* AT91C_TC0_CMR is implicitly set to */ +					/* AT91C_TC_TIMER_DIV1_CLOCK */ + +#define CONFIG_STACKSIZE	(32*1024)	/* regular stack */ + +#ifdef CONFIG_USE_IRQ +#error CONFIG_USE_IRQ not supported +#endif + +#endif |