@ -17,7 +17,6 @@
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place - Suite 330 , Boston , MA 02111 - 1307 , USA
*/
# ident "$Id:$"
/*
* The Xilinx SystemACE chip support is activated by defining
@ -34,16 +33,16 @@
*
* According to Xilinx technical support , before accessing the
* SystemACE CF you need to set the following control bits :
* FORCECFGMODE : 1
* CFGMODE : 0
* CFGSTART : 0
* FORCECFGMODE : 1
* CFGMODE : 0
* CFGSTART : 0
*/
# include <common.h>
# include <command.h>
# include <systemace.h>
# include <part.h>
# include <asm / io.h>
# include <common.h>
# include <command.h>
# include <systemace.h>
# include <part.h>
# include <asm/ io.h>
# ifdef CONFIG_SYSTEMACE
@ -57,18 +56,18 @@
static unsigned ace_readw ( unsigned offset )
{
# if (CFG_SYSTEMACE_WIDTH == 8)
u16 temp ;
u16 temp ;
# if !defined(__BIG_ENDIAN)
temp = ( ( u16 ) readb ( CFG_SYSTEMACE_BASE + offset ) < < 8 ) ;
temp | = ( u16 ) readb ( CFG_SYSTEMACE_BASE + offset + 1 ) ;
temp = ( ( u16 ) readb ( CFG_SYSTEMACE_BASE + offset ) < < 8 ) ;
temp | = ( u16 ) readb ( CFG_SYSTEMACE_BASE + offset + 1 ) ;
# else
temp = ( u16 ) readb ( CFG_SYSTEMACE_BASE + offset ) ;
temp | = ( ( u16 ) readb ( CFG_SYSTEMACE_BASE + offset + 1 ) < < 8 ) ;
temp = ( u16 ) readb ( CFG_SYSTEMACE_BASE + offset ) ;
temp | = ( ( u16 ) readb ( CFG_SYSTEMACE_BASE + offset + 1 ) < < 8 ) ;
# endif
return temp ;
return temp ;
# else
return readw ( CFG_SYSTEMACE_BASE + offset ) ;
return readw ( CFG_SYSTEMACE_BASE + offset ) ;
# endif
}
@ -76,73 +75,72 @@ static void ace_writew(unsigned val, unsigned offset)
{
# if (CFG_SYSTEMACE_WIDTH == 8)
# if !defined(__BIG_ENDIAN)
writeb ( ( u8 ) ( val > > 8 ) , CFG_SYSTEMACE_BASE + offset ) ;
writeb ( ( u8 ) val , CFG_SYSTEMACE_BASE + offset + 1 ) ;
writeb ( ( u8 ) ( val > > 8 ) , CFG_SYSTEMACE_BASE + offset ) ;
writeb ( ( u8 ) val , CFG_SYSTEMACE_BASE + offset + 1 ) ;
# else
writeb ( ( u8 ) val , CFG_SYSTEMACE_BASE + offset ) ;
writeb ( ( u8 ) ( val > > 8 ) , CFG_SYSTEMACE_BASE + offset + 1 ) ;
writeb ( ( u8 ) val , CFG_SYSTEMACE_BASE + offset ) ;
writeb ( ( u8 ) ( val > > 8 ) , CFG_SYSTEMACE_BASE + offset + 1 ) ;
# endif
# else
writew ( val , CFG_SYSTEMACE_BASE + offset ) ;
writew ( val , CFG_SYSTEMACE_BASE + offset ) ;
# endif
}
/* */
static unsigned long systemace_read ( int dev ,
unsigned long start ,
unsigned long blkcnt ,
unsigned long * buffer ) ;
static unsigned long systemace_read ( int dev , unsigned long start ,
unsigned long blkcnt ,
unsigned long * buffer ) ;
static block_dev_desc_t systemace_dev = { 0 } ;
static block_dev_desc_t systemace_dev = { 0 } ;
static int get_cf_lock ( void )
{
int retry = 10 ;
int retry = 10 ;
/* CONTROLREG = LOCKREG */
unsigned val = ace_readw ( 0x18 ) ;
val | = 0x0002 ;
ace_writew ( ( val & 0xffff ) , 0x18 ) ;
unsigned val = ace_readw ( 0x18 ) ;
val | = 0x0002 ;
ace_writew ( ( val & 0xffff ) , 0x18 ) ;
/* Wait for MPULOCK in STATUSREG[15:0] */
while ( ! ( ace_readw ( 0x04 ) & 0x0002 ) ) {
while ( ! ( ace_readw ( 0x04 ) & 0x0002 ) ) {
if ( retry < 0 )
return - 1 ;
if ( retry < 0 )
return - 1 ;
udelay ( 100000 ) ;
retry - = 1 ;
}
udelay ( 100000 ) ;
retry - = 1 ;
}
return 0 ;
return 0 ;
}
static void release_cf_lock ( void )
{
unsigned val = ace_readw ( 0x18 ) ;
val & = ~ ( 0x0002 ) ;
ace_writew ( ( val & 0xffff ) , 0x18 ) ;
unsigned val = ace_readw ( 0x18 ) ;
val & = ~ ( 0x0002 ) ;
ace_writew ( ( val & 0xffff ) , 0x18 ) ;
}
block_dev_desc_t * systemace_get_dev ( int dev )
block_dev_desc_t * systemace_get_dev ( int dev )
{
/* The first time through this, the systemace_dev object is
not yet initialized . In that case , fill it in . */
if ( systemace_dev . blksz = = 0 ) {
systemace_dev . if_type = IF_TYPE_UNKNOWN ;
systemace_dev . dev = 0 ;
systemace_dev . part_type = PART_TYPE_UNKNOWN ;
systemace_dev . type = DEV_TYPE_HARDDISK ;
systemace_dev . blksz = 512 ;
systemace_dev . removable = 1 ;
systemace_dev . block_read = systemace_read ;
if ( systemace_dev . blksz = = 0 ) {
systemace_dev . if_type = IF_TYPE_UNKNOWN ;
systemace_dev . dev = 0 ;
systemace_dev . part_type = PART_TYPE_UNKNOWN ;
systemace_dev . type = DEV_TYPE_HARDDISK ;
systemace_dev . blksz = 512 ;
systemace_dev . removable = 1 ;
systemace_dev . block_read = systemace_read ;
init_part ( & systemace_dev ) ;
init_part ( & systemace_dev ) ;
}
}
return & systemace_dev ;
return & systemace_dev ;
}
/*
@ -150,118 +148,117 @@ block_dev_desc_t * systemace_get_dev(int dev)
* the dev_desc ) to read blocks of data . The return value is the
* number of blocks read . A zero return indicates an error .
*/
static unsigned long systemace_read ( int dev ,
unsigned long start ,
unsigned long blkcnt ,
unsigned long * buffer )
static unsigned long systemace_read ( int dev , unsigned long start ,
unsigned long blkcnt , unsigned long * buffer )
{
int retry ;
unsigned blk_countdown ;
unsigned char * dp = ( unsigned char * ) buffer ;
unsigned val ;
if ( get_cf_lock ( ) < 0 ) {
unsigned status = ace_readw ( 0x04 ) ;
/* If CFDETECT is false, card is missing. */
if ( ! ( status & 0x0010 ) ) {
printf ( " ** CompactFlash card not present. ** \n " ) ;
return 0 ;
}
printf ( " **** ACE locked away from me (STATUSREG=%04x) \n " , status ) ;
return 0 ;
}
int retry ;
unsigned blk_countdown ;
unsigned char * dp = ( unsigned char * ) buffer ;
unsigned val ;
if ( get_cf_lock ( ) < 0 ) {
unsigned status = ace_readw ( 0x04 ) ;
/* If CFDETECT is false, card is missing. */
if ( ! ( status & 0x0010 ) ) {
printf ( " ** CompactFlash card not present. ** \n " ) ;
return 0 ;
}
printf ( " **** ACE locked away from me (STATUSREG=%04x) \n " ,
status ) ;
return 0 ;
}
# ifdef DEBUG_SYSTEMACE
printf ( " ... systemace read %lu sectors at %lu \n " , blkcnt , start ) ;
printf ( " ... systemace read %lu sectors at %lu \n " , blkcnt , start ) ;
# endif
retry = 2000 ;
for ( ; ; ) {
val = ace_readw ( 0x04 ) ;
retry = 2000 ;
for ( ; ; ) {
val = ace_readw ( 0x04 ) ;
/* If CFDETECT is false, card is missing. */
if ( ! ( val & 0x0010 ) ) {
printf ( " **** ACE CompactFlash not found. \n " ) ;
release_cf_lock ( ) ;
return 0 ;
}
/* If CFDETECT is false, card is missing. */
if ( ! ( val & 0x0010 ) ) {
printf ( " **** ACE CompactFlash not found. \n " ) ;
release_cf_lock ( ) ;
return 0 ;
}
/* If RDYFORCMD, then we are ready to go. */
if ( val & 0x0100 )
break ;
/* If RDYFORCMD, then we are ready to go. */
if ( val & 0x0100 )
break ;
if ( retry < 0 ) {
printf ( " **** SystemACE not ready. \n " ) ;
release_cf_lock ( ) ;
return 0 ;
}
if ( retry < 0 ) {
printf ( " **** SystemACE not ready. \n " ) ;
release_cf_lock ( ) ;
return 0 ;
}
udelay ( 1000 ) ;
retry - = 1 ;
}
udelay ( 1000 ) ;
retry - = 1 ;
}
/* The SystemACE can only transfer 256 sectors at a time, so
limit the current chunk of sectors . The blk_countdown
variable is the number of sectors left to transfer . */
blk_countdown = blkcnt ;
while ( blk_countdown > 0 ) {
unsigned trans = blk_countdown ;
blk_countdown = blkcnt ;
while ( blk_countdown > 0 ) {
unsigned trans = blk_countdown ;
if ( trans > 256 ) trans = 256 ;
if ( trans > 256 )
trans = 256 ;
# ifdef DEBUG_SYSTEMACE
printf ( " ... transfer %lu sector in a chunk \n " , trans ) ;
printf ( " ... transfer %lu sector in a chunk \n " , trans ) ;
# endif
/* Write LBA block address */
ace_writew ( ( start > > 0 ) & 0xffff , 0x10 ) ;
ace_writew ( ( start > > 16 ) & 0x00ff , 0x12 ) ;
/* NOTE: in the Write Sector count below, a count of 0
causes a transfer of 256 , so & 0xff gives the right
value for whatever transfer count we want . */
/* Write sector count | ReadMemCardData. */
ace_writew ( ( trans & 0xff ) | 0x0300 , 0x14 ) ;
/* Reset the configruation controller */
val = ace_readw ( 0x18 ) ;
val | = 0x0080 ;
ace_writew ( val , 0x18 ) ;
retry = trans * 16 ;
while ( retry > 0 ) {
int idx ;
/* Wait for buffer to become ready. */
while ( ! ( ace_readw ( 0x04 ) & 0x0020 ) ) {
udelay ( 100 ) ;
}
/* Read 16 words of 2bytes from the sector buffer. */
for ( idx = 0 ; idx < 16 ; idx + = 1 ) {
unsigned short val = ace_readw ( 0x40 ) ;
* dp + + = val & 0xff ;
* dp + + = ( val > > 8 ) & 0xff ;
}
retry - = 1 ;
}
/* Clear the configruation controller reset */
val = ace_readw ( 0x18 ) ;
val & = ~ 0x0080 ;
ace_writew ( val , 0x18 ) ;
/* Count the blocks we transfer this time. */
start + = trans ;
blk_countdown - = trans ;
}
release_cf_lock ( ) ;
return blkcnt ;
/* Write LBA block address */
ace_writew ( ( start > > 0 ) & 0xffff , 0x10 ) ;
ace_writew ( ( start > > 16 ) & 0x00ff , 0x12 ) ;
/* NOTE: in the Write Sector count below, a count of 0
causes a transfer of 256 , so & 0xff gives the right
value for whatever transfer count we want . */
/* Write sector count | ReadMemCardData. */
ace_writew ( ( trans & 0xff ) | 0x0300 , 0x14 ) ;
/* Reset the configruation controller */
val = ace_readw ( 0x18 ) ;
val | = 0x0080 ;
ace_writew ( val , 0x18 ) ;
retry = trans * 16 ;
while ( retry > 0 ) {
int idx ;
/* Wait for buffer to become ready. */
while ( ! ( ace_readw ( 0x04 ) & 0x0020 ) ) {
udelay ( 100 ) ;
}
/* Read 16 words of 2bytes from the sector buffer. */
for ( idx = 0 ; idx < 16 ; idx + = 1 ) {
unsigned short val = ace_readw ( 0x40 ) ;
* dp + + = val & 0xff ;
* dp + + = ( val > > 8 ) & 0xff ;
}
retry - = 1 ;
}
/* Clear the configruation controller reset */
val = ace_readw ( 0x18 ) ;
val & = ~ 0x0080 ;
ace_writew ( val , 0x18 ) ;
/* Count the blocks we transfer this time. */
start + = trans ;
blk_countdown - = trans ;
}
release_cf_lock ( ) ;
return blkcnt ;
}
# endif /* CONFIG_SYSTEMACE */
# endif /* CONFIG_SYSTEMACE */