# include <common.h>
# if defined(CONFIG_8xx)
# include <mpc8xx.h>
# endif
# include <pcmcia.h>
# undef CONFIG_PCMCIA
# if defined(CONFIG_CMD_PCMCIA)
# define CONFIG_PCMCIA
# endif
# if defined(CONFIG_CMD_IDE) && defined(CONFIG_IDE_8xx_PCCARD)
# define CONFIG_PCMCIA
# endif
# if defined(CONFIG_8xx) && defined(CONFIG_PCMCIA)
# if defined(CONFIG_IDE_8xx_PCCARD)
extern int check_ide_device ( int slot ) ;
# endif
extern int pcmcia_hardware_enable ( int slot ) ;
extern int pcmcia_voltage_set ( int slot , int vcc , int vpp ) ;
# if defined(CONFIG_CMD_PCMCIA)
extern int pcmcia_hardware_disable ( int slot ) ;
# endif
static u_int m8xx_get_graycode ( u_int size ) ;
#if 0 /* Disabled */
static u_int m8xx_get_speed ( u_int ns , u_int is_io ) ;
# endif
/* look up table for pgcrx registers */
u_int * pcmcia_pgcrx [ 2 ] = {
& ( ( immap_t * ) CFG_IMMR ) - > im_pcmcia . pcmc_pgcra ,
& ( ( immap_t * ) CFG_IMMR ) - > im_pcmcia . pcmc_pgcrb ,
} ;
/*
* Search this table to see if the windowsize is
* supported . . .
*/
# define M8XX_SIZES_NO 32
static const u_int m8xx_size_to_gray [ M8XX_SIZES_NO ] =
{ 0x00000001 , 0x00000002 , 0x00000008 , 0x00000004 ,
0x00000080 , 0x00000040 , 0x00000010 , 0x00000020 ,
0x00008000 , 0x00004000 , 0x00001000 , 0x00002000 ,
0x00000100 , 0x00000200 , 0x00000800 , 0x00000400 ,
0x0fffffff , 0xffffffff , 0xffffffff , 0xffffffff ,
0x01000000 , 0x02000000 , 0xffffffff , 0x04000000 ,
0x00010000 , 0x00020000 , 0x00080000 , 0x00040000 ,
0x00800000 , 0x00400000 , 0x00100000 , 0x00200000 } ;
/* -------------------------------------------------------------------- */
# ifdef CONFIG_HMI10
# define HMI10_FRAM_TIMING ( PCMCIA_SHT(2) \
| PCMCIA_SST ( 2 ) \
| PCMCIA_SL ( 4 ) )
# endif
# if defined(CONFIG_LWMON) || defined(CONFIG_NSCU)
# define CFG_PCMCIA_TIMING ( PCMCIA_SHT(9) \
| PCMCIA_SST ( 3 ) \
| PCMCIA_SL ( 12 ) )
# else
# define CFG_PCMCIA_TIMING ( PCMCIA_SHT(2) \
| PCMCIA_SST ( 4 ) \
| PCMCIA_SL ( 9 ) )
# endif
/* -------------------------------------------------------------------- */
int pcmcia_on ( void )
{
u_long reg , base ;
pcmcia_win_t * win ;
u_int slotbit ;
u_int rc , slot ;
int i ;
debug ( " Enable PCMCIA " PCMCIA_SLOT_MSG " \n " ) ;
/* intialize the fixed memory windows */
win = ( pcmcia_win_t * ) ( & ( ( immap_t * ) CFG_IMMR ) - > im_pcmcia . pcmc_pbr0 ) ;
base = CFG_PCMCIA_MEM_ADDR ;
if ( ( reg = m8xx_get_graycode ( CFG_PCMCIA_MEM_SIZE ) ) = = - 1 ) {
printf ( " Cannot set window size to 0x%08x \n " ,
CFG_PCMCIA_MEM_SIZE ) ;
return ( 1 ) ;
}
slotbit = PCMCIA_SLOT_x ;
for ( i = 0 ; i < PCMCIA_MEM_WIN_NO ; + + i ) {
win - > br = base ;
# if (PCMCIA_SOCKETS_NO == 2)
if ( i = = 4 ) /* Another slot starting from win 4 */
slotbit = ( slotbit ? PCMCIA_PSLOT_A : PCMCIA_PSLOT_B ) ;
# endif
switch ( i ) {
# ifdef CONFIG_IDE_8xx_PCCARD
case 4 :
# ifdef CONFIG_HMI10
{ /* map FRAM area */
win - > or = ( PCMCIA_BSIZE_256K
| PCMCIA_PPS_8
| PCMCIA_PRS_ATTR
| slotbit
| PCMCIA_PV
| HMI10_FRAM_TIMING ) ;
break ;
}
# endif
case 0 : { /* map attribute memory */
win - > or = ( PCMCIA_BSIZE_64M
| PCMCIA_PPS_8
| PCMCIA_PRS_ATTR
| slotbit
| PCMCIA_PV
| CFG_PCMCIA_TIMING ) ;
break ;
}
case 5 :
case 1 : { /* map I/O window for data reg */
win - > or = ( PCMCIA_BSIZE_1K
| PCMCIA_PPS_16
| PCMCIA_PRS_IO
| slotbit
| PCMCIA_PV
| CFG_PCMCIA_TIMING ) ;
break ;
}
case 6 :
case 2 : { /* map I/O window for cmd/ctrl reg block */
win - > or = ( PCMCIA_BSIZE_1K
| PCMCIA_PPS_8
| PCMCIA_PRS_IO
| slotbit
| PCMCIA_PV
| CFG_PCMCIA_TIMING ) ;
break ;
}
# endif /* CONFIG_IDE_8xx_PCCARD */
# ifdef CONFIG_HMI10
case 3 : { /* map I/O window for 4xUART data/ctrl */
win - > br + = 0x40000 ;
win - > or = ( PCMCIA_BSIZE_256K
| PCMCIA_PPS_8
| PCMCIA_PRS_IO
| slotbit
| PCMCIA_PV
| CFG_PCMCIA_TIMING ) ;
break ;
}
# endif /* CONFIG_HMI10 */
default : /* set to not valid */
win - > or = 0 ;
break ;
}
debug ( " MemWin %d: PBR 0x%08lX POR %08lX \n " ,
i , win - > br , win - > or ) ;
base + = CFG_PCMCIA_MEM_SIZE ;
+ + win ;
}
for ( i = 0 , rc = 0 , slot = _slot_ ; i < PCMCIA_SOCKETS_NO ; i + + , slot = ! slot ) {
/* turn off voltage */
if ( ( rc = pcmcia_voltage_set ( slot , 0 , 0 ) ) )
continue ;
/* Enable external hardware */
if ( ( rc = pcmcia_hardware_enable ( slot ) ) )
continue ;
# ifdef CONFIG_IDE_8xx_PCCARD
if ( ( rc = check_ide_device ( i ) ) )
continue ;
# endif
}
return rc ;
}
# if defined(CONFIG_CMD_PCMCIA)
int pcmcia_off ( void )
{
int i ;
pcmcia_win_t * win ;
printf ( " Disable PCMCIA " PCMCIA_SLOT_MSG " \n " ) ;
/* clear interrupt state, and disable interrupts */
( ( immap_t * ) CFG_IMMR ) - > im_pcmcia . pcmc_pscr = PCMCIA_MASK ( _slot_ ) ;
( ( immap_t * ) CFG_IMMR ) - > im_pcmcia . pcmc_per & = ~ PCMCIA_MASK ( _slot_ ) ;
/* turn off interrupt and disable CxOE */
PCMCIA_PGCRX ( _slot_ ) = __MY_PCMCIA_GCRX_CXOE ;
/* turn off memory windows */
win = ( pcmcia_win_t * ) ( & ( ( immap_t * ) CFG_IMMR ) - > im_pcmcia . pcmc_pbr0 ) ;
for ( i = 0 ; i < PCMCIA_MEM_WIN_NO ; + + i ) {
/* disable memory window */
win - > or = 0 ;
+ + win ;
}
/* turn off voltage */
pcmcia_voltage_set ( _slot_ , 0 , 0 ) ;
/* disable external hardware */
printf ( " Shutdown and Poweroff " PCMCIA_SLOT_MSG " \n " ) ;
pcmcia_hardware_disable ( _slot_ ) ;
return 0 ;
}
# endif
static u_int m8xx_get_graycode ( u_int size )
{
u_int k ;
for ( k = 0 ; k < M8XX_SIZES_NO ; k + + ) {
if ( m8xx_size_to_gray [ k ] = = size )
break ;
}
if ( ( k = = M8XX_SIZES_NO ) | | ( m8xx_size_to_gray [ k ] = = - 1 ) )
k = - 1 ;
return k ;
}
#if 0
# if defined(CONFIG_RPXCLASSIC) || defined(CONFIG_RPXLITE)
/* The RPX boards seems to have it's bus monitor timeout set to 6*8 clocks.
* SYPCR is write once only , therefore must the slowest memory be faster
* than the bus monitor or we will get a machine check due to the bus timeout .
*/
# undef PCMCIA_BMT_LIMIT
# define PCMCIA_BMT_LIMIT (6*8)
# endif
static u_int m8xx_get_speed ( u_int ns , u_int is_io )
{
u_int reg , clocks , psst , psl , psht ;
if ( ! ns ) {
/*
* We get called with IO maps setup to 0 ns
* if not specified by the user .
* They should be 255 ns .
*/
if ( is_io )
ns = 255 ;
else
ns = 100 ; /* fast memory if 0 */
}
/*
* In PSST , PSL , PSHT fields we tell the controller
* timing parameters in CLKOUT clock cycles .
* CLKOUT is the same as GCLK2_50 .
*/
/* how we want to adjust the timing - in percent */
# define ADJ 180 /* 80 % longer accesstime - to be sure */
clocks = ( ( M8XX_BUSFREQ / 1000 ) * ns ) / 1000 ;
clocks = ( clocks * ADJ ) / ( 100 * 1000 ) ;
if ( clocks > = PCMCIA_BMT_LIMIT ) {
DEBUG ( 0 , " Max access time limit reached \n " ) ;
clocks = PCMCIA_BMT_LIMIT - 1 ;
}
psst = clocks / 7 ; /* setup time */
psht = clocks / 7 ; /* hold time */
psl = ( clocks * 5 ) / 7 ; /* strobe length */
psst + = clocks - ( psst + psht + psl ) ;
reg = psst < < 12 ;
reg | = psl < < 7 ;
reg | = psht < < 16 ;
return reg ;
}
# endif /* 0 */
# endif /* CONFIG_8xx && CONFIG_PCMCIA */