Skip to content
Snippets Groups Projects
cmd_pcmcia.c 60.7 KiB
Newer Older
  • Learn to ignore specific revisions
  • Wolfgang Denk's avatar
    Wolfgang Denk committed
    	case  0: 			break;
    	case 33: val = MAX1604_VCC_35;	break;
    	case 50: 			break;
    	default: 			goto done;
    	}
    
    	/* Checking supported voltages */
    
    	debug ("PIPR: 0x%x --> %s\n",
    		pcmp->pcmc_pipr,
    		(pcmp->pcmc_pipr & 0x00008000) ? "only 5 V" : "can do 3.3V");
    
    	i2c_write (CFG_I2C_POWER_A_ADDR, 0, 0, &val, 1);
    	if (val) {
    		debug ("PCMCIA powered at %sV\n",
    			(val & MAX1604_VCC_35) ? "3.3" : "5.0");
    	} else {
    		debug ("PCMCIA powered down\n");
    	}
    
    done:
    	debug ("Enable PCMCIA buffers and stop RESET\n");
    	reg  =  PCMCIA_PGCRX(_slot_);
    	reg &= ~__MY_PCMCIA_GCRX_CXRESET;	/* active high */
    	reg &= ~__MY_PCMCIA_GCRX_CXOE;		/* active low  */
    	PCMCIA_PGCRX(_slot_) = reg;
    	udelay(500);
    
    	debug ("voltage_set: " PCMCIA_BOARD_MSG " Slot %c, DONE\n",
    		slot+'A');
    	return (0);
    }
    
    #endif	/* LWMON */
    
    
    /* -------------------------------------------------------------------- */
    /* GTH board by Corelatus AB						*/
    /* -------------------------------------------------------------------- */
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    #if defined(CONFIG_GTH)
    
    #define PCMCIA_BOARD_MSG "GTH COMPACT FLASH"
    
    
    static int voltage_set (int slot, int vcc, int vpp)
    {	/* Do nothing */
    	return 0;
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    }
    
    static int hardware_enable (int slot)
    {
    
    	volatile immap_t *immap;
    	volatile cpm8xx_t *cp;
    	volatile pcmconf8xx_t *pcmp;
    	volatile sysconf8xx_t *sysp;
    	uint reg, mask;
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    
    
    	debug ("hardware_enable: GTH Slot %c\n", 'A' + slot);
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    
    
    	immap = (immap_t *) CFG_IMMR;
    	sysp = (sysconf8xx_t *) (&(((immap_t *) CFG_IMMR)->im_siu_conf));
    	pcmp = (pcmconf8xx_t *) (&(((immap_t *) CFG_IMMR)->im_pcmcia));
    	cp = (cpm8xx_t *) (&(((immap_t *) CFG_IMMR)->im_cpm));
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    
    
    	/* clear interrupt state, and disable interrupts */
    	pcmp->pcmc_pscr = PCMCIA_MASK (_slot_);
    	pcmp->pcmc_per &= ~PCMCIA_MASK (_slot_);
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    
    
    	/*
    	 * Disable interrupts, DMA, and PCMCIA buffers
    	 * (isolate the interface) and assert RESET signal
    	 */
    	debug ("Disable PCMCIA buffers and assert RESET\n");
    	reg = 0;
    	reg |= __MY_PCMCIA_GCRX_CXRESET;	/* active high */
    	reg |= __MY_PCMCIA_GCRX_CXOE;	/* active low  */
    	PCMCIA_PGCRX (_slot_) = reg;
    	udelay (500);
    
    	/*
    	 * Make sure there is a card in the slot,
    	 * then configure the interface.
    	 */
    	udelay (10000);
    	debug ("[%d] %s: PIPR(%p)=0x%x\n",
    		__LINE__, __FUNCTION__,
    		&(pcmp->pcmc_pipr), pcmp->pcmc_pipr);
    	if (pcmp->pcmc_pipr & 0x98000000) {
    		printf ("   No Card found\n");
    		return (1);
    	}
    
    	mask = PCMCIA_VS1 (slot) | PCMCIA_VS2 (slot);
    	reg = pcmp->pcmc_pipr;
    	debug ("PIPR: 0x%x ==> VS1=o%s, VS2=o%s\n",
    		   reg,
    		   (reg & PCMCIA_VS1 (slot)) ? "n" : "ff",
    		   (reg & PCMCIA_VS2 (slot)) ? "n" : "ff");
    
    	debug ("Enable PCMCIA buffers and stop RESET\n");
    	reg  =  PCMCIA_PGCRX (_slot_);
    	reg &= ~__MY_PCMCIA_GCRX_CXRESET;	/* active high */
    	reg &= ~__MY_PCMCIA_GCRX_CXOE;		/* active low  */
    	PCMCIA_PGCRX (_slot_) = reg;
    
    	udelay (250000);	/* some cards need >150 ms to come up :-( */
    
    	debug ("# hardware_enable done\n");
    
    	return 0;
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    }
    #if (CONFIG_COMMANDS & CFG_CMD_PCMCIA)
    static int hardware_disable(int slot)
    {
    	return 0;	/* No hardware to disable */
    }
    #endif	/* CFG_CMD_PCMCIA */
    #endif	/* CONFIG_GTH */
    
    
    /* -------------------------------------------------------------------- */
    /* ICU862 Boards by Cambridge Broadband Ltd.				*/
    /* -------------------------------------------------------------------- */
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    
    #if defined(CONFIG_ICU862)
    
    #define PCMCIA_BOARD_MSG "ICU862"
    
    static void cfg_port_B (void);
    
    static int hardware_enable(int slot)
    {
    	volatile immap_t	*immap;
    	volatile cpm8xx_t	*cp;
    	volatile pcmconf8xx_t	*pcmp;
    	volatile sysconf8xx_t	*sysp;
    	uint reg, pipr, mask;
    	int i;
    
    	debug ("hardware_enable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot);
    
    	udelay(10000);
    
    	immap = (immap_t *)CFG_IMMR;
    	sysp  = (sysconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_siu_conf));
    	pcmp  = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia));
    	cp    = (cpm8xx_t *)(&(((immap_t *)CFG_IMMR)->im_cpm));
    
    	/* Configure Port B for TPS2205 PC-Card Power-Interface Switch */
    	cfg_port_B ();
    
    	/*
    	 * Configure SIUMCR to enable PCMCIA port B
    	 * (VFLS[0:1] are not used for debugging, we connect FRZ# instead)
    	 */
    	sysp->sc_siumcr &= ~SIUMCR_DBGC11;	/* set DBGC to 00 */
    
    	/* clear interrupt state, and disable interrupts */
    	pcmp->pcmc_pscr =  PCMCIA_MASK(_slot_);
    	pcmp->pcmc_per &= ~PCMCIA_MASK(_slot_);
    
    	/*
    
    	 * Disable interrupts, DMA, and PCMCIA buffers
    	 * (isolate the interface) and assert RESET signal
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    	 */
    	debug ("Disable PCMCIA buffers and assert RESET\n");
    
    	reg  = 0;
    	reg |= __MY_PCMCIA_GCRX_CXRESET;	/* active high */
    	reg |= __MY_PCMCIA_GCRX_CXOE;		/* active low  */
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    	PCMCIA_PGCRX(_slot_) = reg;
    	udelay(500);
    
    	/*
    	 * Make sure there is a card in the slot, then configure the interface.
    	 */
    	udelay(10000);
    	debug ("[%d] %s: PIPR(%p)=0x%x\n",
    		__LINE__,__FUNCTION__,
    		&(pcmp->pcmc_pipr),pcmp->pcmc_pipr);
    
    	if (pcmp->pcmc_pipr & (0x18000000 >> (slot << 4))) {
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    		printf ("   No Card found\n");
    		return (1);
    	}
    
    	/*
    	 * Power On: Set VAVCC to 3.3V or 5V, set VAVPP to Hi-Z
    	 */
    	mask = PCMCIA_VS1(slot) | PCMCIA_VS2(slot);
    	pipr = pcmp->pcmc_pipr;
    	debug ("PIPR: 0x%x ==> VS1=o%s, VS2=o%s\n",
    		pipr,
    		(reg&PCMCIA_VS1(slot))?"n":"ff",
    		(reg&PCMCIA_VS2(slot))?"n":"ff");
    
    	reg  = cp->cp_pbdat;
    	if ((pipr & mask) == mask) {
    
    		reg |= (TPS2205_VPP_PGM | TPS2205_VPP_VCC |	/* VAVPP => Hi-Z */
    			TPS2205_VCC3);				/* 3V off	*/
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    		reg &= ~(TPS2205_VCC5);				/* 5V on	*/
    		puts (" 5.0V card found: ");
    	} else {
    
    		reg |= (TPS2205_VPP_PGM | TPS2205_VPP_VCC |	/* VAVPP => Hi-Z */
    			TPS2205_VCC5);				/* 5V off	*/
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    		reg &= ~(TPS2205_VCC3);				/* 3V on	*/
    		puts (" 3.3V card found: ");
    	}
    
    	debug ("\nPB DAT: %08x -> 3.3V %s 5.0V %s VPP_PGM %s VPP_VCC %s\n",
    		reg,
    		(reg & TPS2205_VCC3)    ? "off" : "on",
    		(reg & TPS2205_VCC5)    ? "off" : "on",
    		(reg & TPS2205_VPP_PGM) ? "off" : "on",
    		(reg & TPS2205_VPP_VCC) ? "off" : "on" );
    
    	cp->cp_pbdat = reg;
    
    	/*  Wait 500 ms; use this to check for over-current */
    	for (i=0; i<5000; ++i) {
    		if ((cp->cp_pbdat & TPS2205_OC) == 0) {
    			printf ("   *** Overcurrent - Safety shutdown ***\n");
    			cp->cp_pbdat &= ~(TPS2205_SHDN);
    			return (1);
    		}
    		udelay (100);
    	}
    
    	debug ("Enable PCMCIA buffers and stop RESET\n");
    	reg  =  PCMCIA_PGCRX(_slot_);
    	reg &= ~__MY_PCMCIA_GCRX_CXRESET;	/* active high */
    	reg &= ~__MY_PCMCIA_GCRX_CXOE;		/* active low  */
    	PCMCIA_PGCRX(_slot_) = reg;
    
    	udelay(250000);	/* some cards need >150 ms to come up :-( */
    
    	debug ("# hardware_enable done\n");
    
    	return (0);
    }
    
    
    #if (CONFIG_COMMANDS & CFG_CMD_PCMCIA)
    static int hardware_disable(int slot)
    {
    	volatile immap_t	*immap;
    	volatile cpm8xx_t	*cp;
    	volatile pcmconf8xx_t	*pcmp;
    	u_long reg;
    
    	debug ("hardware_disable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot);
    
    	immap = (immap_t *)CFG_IMMR;
    	cp    = (cpm8xx_t *)(&(((immap_t *)CFG_IMMR)->im_cpm));
    	pcmp  = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia));
    
    	/* Shut down */
    	cp->cp_pbdat &= ~(TPS2205_SHDN);
    
    	/* Configure PCMCIA General Control Register */
    	debug ("Disable PCMCIA buffers and assert RESET\n");
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    	reg |= __MY_PCMCIA_GCRX_CXRESET;	/* active high */
    	reg |= __MY_PCMCIA_GCRX_CXOE;		/* active low  */
    	PCMCIA_PGCRX(_slot_) = reg;
    
    	udelay(10000);
    
    	return (0);
    }
    #endif	/* CFG_CMD_PCMCIA */
    
    
    static int voltage_set(int slot, int vcc, int vpp)
    {
    	volatile immap_t	*immap;
    	volatile cpm8xx_t	*cp;
    	volatile pcmconf8xx_t	*pcmp;
    	u_long reg;
    
    	debug ("voltage_set: "
    		PCMCIA_BOARD_MSG
    		" Slot %c, Vcc=%d.%d, Vpp=%d.%d\n",
    		'A'+slot, vcc/10, vcc%10, vpp/10, vcc%10);
    
    	immap = (immap_t *)CFG_IMMR;
    	cp    = (cpm8xx_t *)(&(((immap_t *)CFG_IMMR)->im_cpm));
    	pcmp  = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia));
    	/*
    	 * Disable PCMCIA buffers (isolate the interface)
    	 * and assert RESET signal
    	 */
    	debug ("Disable PCMCIA buffers and assert RESET\n");
    
    	reg  = PCMCIA_PGCRX(_slot_);
    	reg |= __MY_PCMCIA_GCRX_CXRESET;	/* active high */
    	reg |= __MY_PCMCIA_GCRX_CXOE;		/* active low  */
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    	PCMCIA_PGCRX(_slot_) = reg;
    	udelay(500);
    
    	/*
    	 * Configure Port C pins for
    	 * 5 Volts Enable and 3 Volts enable,
    	 * Turn all power pins to Hi-Z
    	 */
    	debug ("PCMCIA power OFF\n");
    	cfg_port_B ();	/* Enables switch, but all in Hi-Z */
    
    	reg  = cp->cp_pbdat;
    
    	switch(vcc) {
    	case  0: 			break;	/* Switch off		*/
    	case 33: reg &= ~TPS2205_VCC3;	break;	/* Switch on 3.3V	*/
    	case 50: reg &= ~TPS2205_VCC5;	break;	/* Switch on 5.0V	*/
    	default: 			goto done;
    	}
    
    	/* Checking supported voltages */
    
    	debug ("PIPR: 0x%x --> %s\n",
    		pcmp->pcmc_pipr,
    		(pcmp->pcmc_pipr & 0x00008000) ? "only 5 V" : "can do 3.3V");
    
    	cp->cp_pbdat = reg;
    
    #ifdef DEBUG
        {
    	char *s;
    
    	if ((reg & TPS2205_VCC3) == 0) {
    		s = "at 3.3V";
    	} else if ((reg & TPS2205_VCC5) == 0) {
    		s = "at 5.0V";
    	} else {
    		s = "down";
    	}
    	printf ("PCMCIA powered %s\n", s);
        }
    #endif
    
    done:
    	debug ("Enable PCMCIA buffers and stop RESET\n");
    	reg  =  PCMCIA_PGCRX(_slot_);
    	reg &= ~__MY_PCMCIA_GCRX_CXRESET;	/* active high */
    	reg &= ~__MY_PCMCIA_GCRX_CXOE;		/* active low  */
    	PCMCIA_PGCRX(_slot_) = reg;
    	udelay(500);
    
    	debug ("voltage_set: " PCMCIA_BOARD_MSG " Slot %c, DONE\n",
    		slot+'A');
    	return (0);
    }
    
    static void cfg_port_B (void)
    {
    	volatile immap_t	*immap;
    	volatile cpm8xx_t	*cp;
    	uint reg;
    
    	immap = (immap_t *)CFG_IMMR;
    	cp    = (cpm8xx_t *)(&(((immap_t *)CFG_IMMR)->im_cpm));
    
    	/*
    	 * Configure Port B for TPS2205 PC-Card Power-Interface Switch
    	 *
    	 * Switch off all voltages, assert shutdown
    	 */
    	reg  = cp->cp_pbdat;
    
    	reg |= (TPS2205_VPP_PGM | TPS2205_VPP_VCC |	/* VAVPP => Hi-Z */
    		TPS2205_VCC3    | TPS2205_VCC5    |	/* VAVCC => Hi-Z */
    		TPS2205_SHDN);				/* enable switch */
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    	cp->cp_pbdat = reg;
    
    	cp->cp_pbpar &= ~(TPS2205_INPUTS | TPS2205_OUTPUTS);
    
    	reg = cp->cp_pbdir & ~(TPS2205_INPUTS);
    	cp->cp_pbdir = reg | TPS2205_OUTPUTS;
    
    	debug ("Set Port B: PAR: %08x DIR: %08x DAT: %08x\n",
    		cp->cp_pbpar, cp->cp_pbdir, cp->cp_pbdat);
    }
    
    #endif	/* ICU862 */
    
    
    
    /* -------------------------------------------------------------------- */
    /* C2MON Boards by TTTech Computertechnik AG				*/
    /* -------------------------------------------------------------------- */
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    
    #if defined(CONFIG_C2MON)
    
    #define PCMCIA_BOARD_MSG "C2MON"
    
    static void cfg_ports (void);
    
    static int hardware_enable(int slot)
    {
    	volatile immap_t	*immap;
    	volatile cpm8xx_t	*cp;
    	volatile pcmconf8xx_t	*pcmp;
    	volatile sysconf8xx_t	*sysp;
    	uint reg, pipr, mask;
    	ushort sreg;
    	int i;
    
    	debug ("hardware_enable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot);
    
    	udelay(10000);
    
    	immap = (immap_t *)CFG_IMMR;
    	sysp  = (sysconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_siu_conf));
    	pcmp  = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia));
    	cp    = (cpm8xx_t *)(&(((immap_t *)CFG_IMMR)->im_cpm));
    
    	/* Configure Ports for TPS2211A PC-Card Power-Interface Switch */
    	cfg_ports ();
    
    	/*
    	 * Configure SIUMCR to enable PCMCIA port B
    	 * (VFLS[0:1] are not used for debugging, we connect FRZ# instead)
    	 */
    	sysp->sc_siumcr &= ~SIUMCR_DBGC11;	/* set DBGC to 00 */
    
    	/* clear interrupt state, and disable interrupts */
    	pcmp->pcmc_pscr =  PCMCIA_MASK(_slot_);
    	pcmp->pcmc_per &= ~PCMCIA_MASK(_slot_);
    
    	/*
    
    	 * Disable interrupts, DMA, and PCMCIA buffers
    	 * (isolate the interface) and assert RESET signal
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    	 */
    	debug ("Disable PCMCIA buffers and assert RESET\n");
    
    	reg  = 0;
    	reg |= __MY_PCMCIA_GCRX_CXRESET;	/* active high */
    	reg |= __MY_PCMCIA_GCRX_CXOE;		/* active low  */
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    	PCMCIA_PGCRX(_slot_) = reg;
    	udelay(500);
    
    	/*
    	 * Make sure there is a card in the slot, then configure the interface.
    	 */
    	udelay(10000);
    	debug ("[%d] %s: PIPR(%p)=0x%x\n",
    		__LINE__,__FUNCTION__,
    		&(pcmp->pcmc_pipr),pcmp->pcmc_pipr);
    
    	if (pcmp->pcmc_pipr & (0x18000000 >> (slot << 4))) {
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    		printf ("   No Card found\n");
    		return (1);
    	}
    
    	/*
    	 * Power On: Set VAVCC to 3.3V or 5V, set VAVPP to Hi-Z
    	 */
    	mask = PCMCIA_VS1(slot) | PCMCIA_VS2(slot);
    	pipr = pcmp->pcmc_pipr;
    	debug ("PIPR: 0x%x ==> VS1=o%s, VS2=o%s\n",
    		pipr,
    		(reg&PCMCIA_VS1(slot))?"n":"ff",
    		(reg&PCMCIA_VS2(slot))?"n":"ff");
    
    	sreg = immap->im_ioport.iop_pcdat;
    	if ((pipr & mask) == mask) {
    		sreg |=  (TPS2211_VPPD0 | TPS2211_VPPD1 |	/* VAVPP => Hi-Z */
    			  TPS2211_VCCD1);			/* 5V on	*/
    		sreg &= ~(TPS2211_VCCD0);			/* 3V off	*/
    		puts (" 5.0V card found: ");
    	} else {
    		sreg |=  (TPS2211_VPPD0 | TPS2211_VPPD1 |	/* VAVPP => Hi-Z */
    			  TPS2211_VCCD0);			/* 3V on	*/
    		sreg &= ~(TPS2211_VCCD1);			/* 5V off	*/
    		puts (" 3.3V card found: ");
    	}
    
    	debug ("\nPC DAT: %04x -> 3.3V %s 5.0V %s\n",
    		sreg,
    		( (sreg & TPS2211_VCCD0) && !(sreg & TPS2211_VCCD1)) ? "on" : "off",
    		(!(sreg & TPS2211_VCCD0) &&  (sreg & TPS2211_VCCD1)) ? "on" : "off"
    	);
    
    	immap->im_ioport.iop_pcdat = sreg;
    
    	/*  Wait 500 ms; use this to check for over-current */
    	for (i=0; i<5000; ++i) {
    		if ((cp->cp_pbdat & TPS2211_OC) == 0) {
    		    printf ("   *** Overcurrent - Safety shutdown ***\n");
    		    immap->im_ioport.iop_pcdat &= ~(TPS2211_VCCD0|TPS2211_VCCD1);
    		    return (1);
    		}
    		udelay (100);
    	}
    
    	debug ("Enable PCMCIA buffers and stop RESET\n");
    	reg  =  PCMCIA_PGCRX(_slot_);
    	reg &= ~__MY_PCMCIA_GCRX_CXRESET;	/* active high */
    	reg &= ~__MY_PCMCIA_GCRX_CXOE;		/* active low  */
    	PCMCIA_PGCRX(_slot_) = reg;
    
    	udelay(250000);	/* some cards need >150 ms to come up :-( */
    
    	debug ("# hardware_enable done\n");
    
    	return (0);
    }
    
    
    #if (CONFIG_COMMANDS & CFG_CMD_PCMCIA)
    static int hardware_disable(int slot)
    {
    	volatile immap_t	*immap;
    	volatile cpm8xx_t	*cp;
    	volatile pcmconf8xx_t	*pcmp;
    	u_long reg;
    
    	debug ("hardware_disable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot);
    
    	immap = (immap_t *)CFG_IMMR;
    	pcmp  = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia));
    
    	/* Configure PCMCIA General Control Register */
    	debug ("Disable PCMCIA buffers and assert RESET\n");
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    	reg |= __MY_PCMCIA_GCRX_CXRESET;	/* active high */
    	reg |= __MY_PCMCIA_GCRX_CXOE;		/* active low  */
    	PCMCIA_PGCRX(_slot_) = reg;
    
    	/* ALl voltages off / Hi-Z */
    	immap->im_ioport.iop_pcdat |= (TPS2211_VPPD0 | TPS2211_VPPD1 |
    				       TPS2211_VCCD0 | TPS2211_VCCD1 );
    
    	udelay(10000);
    
    	return (0);
    }
    #endif	/* CFG_CMD_PCMCIA */
    
    
    static int voltage_set(int slot, int vcc, int vpp)
    {
    	volatile immap_t	*immap;
    	volatile cpm8xx_t	*cp;
    	volatile pcmconf8xx_t	*pcmp;
    	u_long reg;
    	ushort sreg;
    
    	debug ("voltage_set: "
    		PCMCIA_BOARD_MSG
    		" Slot %c, Vcc=%d.%d, Vpp=%d.%d\n",
    		'A'+slot, vcc/10, vcc%10, vpp/10, vcc%10);
    
    	immap = (immap_t *)CFG_IMMR;
    	cp    = (cpm8xx_t *)(&(((immap_t *)CFG_IMMR)->im_cpm));
    	pcmp  = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia));
    	/*
    	 * Disable PCMCIA buffers (isolate the interface)
    	 * and assert RESET signal
    	 */
    	debug ("Disable PCMCIA buffers and assert RESET\n");
    
    	reg  = PCMCIA_PGCRX(_slot_);
    	reg |= __MY_PCMCIA_GCRX_CXRESET;	/* active high */
    	reg |= __MY_PCMCIA_GCRX_CXOE;		/* active low  */
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    	PCMCIA_PGCRX(_slot_) = reg;
    	udelay(500);
    
    	/*
    	 * Configure Port C pins for
    	 * 5 Volts Enable and 3 Volts enable,
    	 * Turn all power pins to Hi-Z
    	 */
    	debug ("PCMCIA power OFF\n");
    	cfg_ports ();	/* Enables switch, but all in Hi-Z */
    
    	sreg  = immap->im_ioport.iop_pcdat;
    	sreg |= TPS2211_VPPD0 | TPS2211_VPPD1;		/* VAVPP always Hi-Z */
    
    	switch(vcc) {
    	case  0: 			break;	/* Switch off		*/
    	case 33: sreg |=  TPS2211_VCCD0;	/* Switch on 3.3V	*/
    		 sreg &= ~TPS2211_VCCD1;
    		 			break;
    	case 50: sreg &= ~TPS2211_VCCD0;	/* Switch on 5.0V	*/
    		 sreg |=  TPS2211_VCCD1;
    		 			break;
    	default: 			goto done;
    	}
    
    	/* Checking supported voltages */
    
    	debug ("PIPR: 0x%x --> %s\n",
    		pcmp->pcmc_pipr,
    		(pcmp->pcmc_pipr & 0x00008000) ? "only 5 V" : "can do 3.3V");
    
    	immap->im_ioport.iop_pcdat = sreg;
    
    #ifdef DEBUG
        {
    	char *s;
    
    	if ((sreg & TPS2211_VCCD0) && !(sreg & TPS2211_VCCD1)) {
    		s = "at 3.3V";
    	} else if (!(sreg & TPS2211_VCCD0) &&  (sreg & TPS2211_VCCD1)) {
    		s = "at 5.0V";
    	} else {
    		s = "down";
    	}
    	printf ("PCMCIA powered %s\n", s);
        }
    #endif
    
    done:
    	debug ("Enable PCMCIA buffers and stop RESET\n");
    	reg  =  PCMCIA_PGCRX(_slot_);
    	reg &= ~__MY_PCMCIA_GCRX_CXRESET;	/* active high */
    	reg &= ~__MY_PCMCIA_GCRX_CXOE;		/* active low  */
    	PCMCIA_PGCRX(_slot_) = reg;
    	udelay(500);
    
    	debug ("voltage_set: " PCMCIA_BOARD_MSG " Slot %c, DONE\n",
    		slot+'A');
    	return (0);
    }
    
    static void cfg_ports (void)
    {
    	volatile immap_t	*immap;
    	volatile cpm8xx_t	*cp;
    	ushort sreg;
    
    	immap = (immap_t *)CFG_IMMR;
    	cp    = (cpm8xx_t *)(&(((immap_t *)CFG_IMMR)->im_cpm));
    
    	/*
    	 * Configure Port C for TPS2211 PC-Card Power-Interface Switch
    	 *
    	 * Switch off all voltages, assert shutdown
    	 */
    	sreg = immap->im_ioport.iop_pcdat;
    	sreg |=  (TPS2211_VPPD0 | TPS2211_VPPD1);	/* VAVPP => Hi-Z */
    	sreg &= ~(TPS2211_VCCD0 | TPS2211_VCCD1);	/* 3V and 5V off */
    	immap->im_ioport.iop_pcdat = sreg;
    
    	immap->im_ioport.iop_pcpar &= ~(TPS2211_OUTPUTS);
    	immap->im_ioport.iop_pcdir |=   TPS2211_OUTPUTS;
    
    	debug ("Set Port C: PAR:     %04x DIR:     %04x DAT:     %04x\n",
    		immap->im_ioport.iop_pcpar,
    		immap->im_ioport.iop_pcdir,
    		immap->im_ioport.iop_pcdat);
    
    	/*
    	 * Configure Port B for TPS2211 PC-Card Power-Interface Switch
    	 *
    	 * Over-Current Input only
    	 */
    	cp->cp_pbpar &= ~(TPS2211_INPUTS);
    	cp->cp_pbdir &= ~(TPS2211_INPUTS);
    
    	debug ("Set Port B: PAR: %08x DIR: %08x DAT: %08x\n",
    		cp->cp_pbpar, cp->cp_pbdir, cp->cp_pbdat);
    }
    
    #endif	/* C2MON */
    
    
    /* -------------------------------------------------------------------- */
    /* MBX board from Morotola						*/
    /* -------------------------------------------------------------------- */
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    
    #if defined( CONFIG_MBX )
    #include <../board/mbx8xx/csr.h>
    
    /* A lot of this has been taken from the RPX code in this file it works from me.
       I have added the voltage selection for the MBX board. */
    
    /* MBX voltage bit in control register #2 */
    #define CR2_VPP12       ((uchar)0x10)
    #define CR2_VPPVDD      ((uchar)0x20)
    #define CR2_VDD5        ((uchar)0x40)
    #define CR2_VDD3        ((uchar)0x80)
    
    #define PCMCIA_BOARD_MSG "MBX860"
    
    static int voltage_set (int slot, int vcc, int vpp)
    {
    	uchar reg = 0;
    
    	debug ("voltage_set: PCMCIA_BOARD_MSG Slot %c, Vcc=%d.%d, Vpp=%d.%d\n",
    		 'A' + slot, vcc / 10, vcc % 10, vpp / 10, vcc % 10);
    
    	switch (vcc) {
    	case 0:
    		break;
    	case 33:
    		reg |= CR2_VDD3;
    		break;
    	case 50:
    		reg |= CR2_VDD5;
    		break;
    	default:
    		return 1;
    	}
    
    	switch (vpp) {
    	case 0:
    		break;
    	case 33:
    	case 50:
    		if (vcc == vpp) {
    			reg |= CR2_VPPVDD;
    		} else {
    			return 1;
    		}
    		break;
    	case 120:
    		reg |= CR2_VPP12;
    		break;
    	default:
    		return 1;
    	}
    
    	/* first, turn off all power */
    	MBX_CSR2 &= ~(CR2_VDDSEL | CR2_VPPSEL);
    
    	/* enable new powersettings */
    	MBX_CSR2 |= reg;
    	debug ("MBX_CSR2 read = 0x%02x\n", MBX_CSR2);
    
    	return (0);
    }
    
    static int hardware_enable (int slot)
    {
    	volatile immap_t *immap;
    	volatile cpm8xx_t *cp;
    	volatile pcmconf8xx_t *pcmp;
    	volatile sysconf8xx_t *sysp;
    	uint reg, mask;
    
    	debug ("hardware_enable: " PCMCIA_BOARD_MSG " Slot %c\n",
    				  'A' + slot);
    
    	udelay (10000);
    
    	immap = (immap_t *) CFG_IMMR;
    	sysp = (sysconf8xx_t *) (&(((immap_t *) CFG_IMMR)->im_siu_conf));
    	pcmp = (pcmconf8xx_t *) (&(((immap_t *) CFG_IMMR)->im_pcmcia));
    	cp = (cpm8xx_t *) (&(((immap_t *) CFG_IMMR)->im_cpm));
    
    	/* clear interrupt state, and disable interrupts */
    	pcmp->pcmc_pscr = PCMCIA_MASK (_slot_);
    	pcmp->pcmc_per &= ~PCMCIA_MASK (_slot_);
    
    	/*
    
    	 * Disable interrupts, DMA, and PCMCIA buffers
    	 * (isolate the interface) and assert RESET signal
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    	 */
    	debug ("Disable PCMCIA buffers and assert RESET\n");
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    	reg |= __MY_PCMCIA_GCRX_CXRESET;	/* active high */
    	reg |= __MY_PCMCIA_GCRX_CXOE;	/* active low  */
    	PCMCIA_PGCRX (_slot_) = reg;
    	udelay (500);
    
    	/* remove all power */
    	voltage_set (slot, 0, 0);
    	/*
    	 * Make sure there is a card in the slot, then configure the interface.
    	 */
    
    	udelay(10000);
    	debug ("[%d] %s: PIPR(%p)=0x%x\n",
    		__LINE__,__FUNCTION__,
    		&(pcmp->pcmc_pipr),pcmp->pcmc_pipr);
    	if (pcmp->pcmc_pipr & (0x18000000 >> (slot << 4))) {
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    		printf ("   No Card found\n");
    		return (1);
    	}
    
    	/*
    	 * Power On.
    	 */
    	mask = PCMCIA_VS1 (_slot_) | PCMCIA_VS2 (_slot_);
    	reg = pcmp->pcmc_pipr;
    	debug ("PIPR: 0x%x ==> VS1=o%s, VS2=o%s\n", reg,
    		  (reg & PCMCIA_VS1 (slot)) ? "n" : "ff",
    		  (reg & PCMCIA_VS2 (slot)) ? "n" : "ff");
    
    	if ((reg & mask) == mask) {
    		voltage_set (_slot_, 50, 0);
    		printf (" 5.0V card found: ");
    	} else {
    		voltage_set (_slot_, 33, 0);
    		printf (" 3.3V card found: ");
    	}
    
    	debug ("Enable PCMCIA buffers and stop RESET\n");
    	reg = PCMCIA_PGCRX (_slot_);
    	reg &= ~__MY_PCMCIA_GCRX_CXRESET;	/* active high */
    	reg &= ~__MY_PCMCIA_GCRX_CXOE;	/* active low  */
    	PCMCIA_PGCRX (_slot_) = reg;
    
    	udelay (250000);	/* some cards need >150 ms to come up :-( */
    
    	debug ("# hardware_enable done\n");
    
    	return (0);
    }
    
    #if (CONFIG_COMMANDS & CFG_CMD_PCMCIA)
    static int hardware_disable (int slot)
    {
    	return 0;	/* No hardware to disable */
    }
    #endif /* CFG_CMD_PCMCIA */
    #endif /* CONFIG_MBX */
    
    /* -------------------------------------------------------------------- */
    /* R360MPI Board							*/
    /* -------------------------------------------------------------------- */
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    
    #if defined(CONFIG_R360MPI)
    
    #define PCMCIA_BOARD_MSG "R360MPI"
    
    
    static int hardware_enable(int slot)
    {
    	volatile immap_t	*immap;
    	volatile cpm8xx_t	*cp;
    	volatile pcmconf8xx_t	*pcmp;
    	volatile sysconf8xx_t	*sysp;
    	uint reg, mask;
    
    	debug ("hardware_enable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot);
    
    	udelay(10000);
    
    	immap = (immap_t *)CFG_IMMR;
    	sysp  = (sysconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_siu_conf));
    	pcmp  = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia));
    	cp    = (cpm8xx_t *)(&(((immap_t *)CFG_IMMR)->im_cpm));
    
    	/*
    	 * Configure SIUMCR to enable PCMCIA port B
    	 * (VFLS[0:1] are not used for debugging, we connect FRZ# instead)
    	 */
    	sysp->sc_siumcr &= ~SIUMCR_DBGC11;	/* set DBGC to 00 */
    
    	/* clear interrupt state, and disable interrupts */
    	pcmp->pcmc_pscr =  PCMCIA_MASK(_slot_);
    	pcmp->pcmc_per &= ~PCMCIA_MASK(_slot_);
    
    	/*
    
    	 * Disable interrupts, DMA, and PCMCIA buffers
    	 * (isolate the interface) and assert RESET signal
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    	 */
    	debug ("Disable PCMCIA buffers and assert RESET\n");
    
    	reg  = 0;
    	reg |= __MY_PCMCIA_GCRX_CXRESET;	/* active high */
    	reg |= __MY_PCMCIA_GCRX_CXOE;		/* active low  */
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    	PCMCIA_PGCRX(_slot_) = reg;
    	udelay(500);
    
    	/*
    	 * Configure Ports A, B & C pins for
    	 * 5 Volts Enable and 3 Volts enable
    	 */
    	immap->im_ioport.iop_pcpar &= ~(0x0400);
    	immap->im_ioport.iop_pcso  &= ~(0x0400);/*
    	immap->im_ioport.iop_pcdir |= 0x0400;*/
    
    	immap->im_ioport.iop_papar &= ~(0x0200);/*
    	immap->im_ioport.iop_padir |= 0x0200;*/
    #if 0
    	immap->im_ioport.iop_pbpar &= ~(0xC000);
    	immap->im_ioport.iop_pbdir &= ~(0xC000);
    #endif
    	/* remove all power */
    
    	immap->im_ioport.iop_pcdat |= 0x0400;
    	immap->im_ioport.iop_padat |= 0x0200;
    
    	/*
    	 * Make sure there is a card in the slot, then configure the interface.
    	 */
    	udelay(10000);
    	debug ("[%d] %s: PIPR(%p)=0x%x\n",
    		__LINE__,__FUNCTION__,
    		&(pcmp->pcmc_pipr),pcmp->pcmc_pipr);
    
    	if (pcmp->pcmc_pipr & (0x18000000 >> (slot << 4))) {
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    		printf ("   No Card found\n");
    		return (1);
    	}
    
    	/*
    	 * Power On.
    	 */
    	mask = PCMCIA_VS1(slot) | PCMCIA_VS2(slot);
    	reg  = pcmp->pcmc_pipr;
    	debug ("PIPR: 0x%x ==> VS1=o%s, VS2=o%s\n",
    		reg,
    		(reg&PCMCIA_VS1(slot))?"n":"ff",
    		(reg&PCMCIA_VS2(slot))?"n":"ff");
    	if ((reg & mask) == mask) {
    		immap->im_ioport.iop_pcdat &= ~(0x4000);
    		puts (" 5.0V card found: ");
    	} else {
    		immap->im_ioport.iop_padat &= ~(0x0002);
    		puts (" 3.3V card found: ");
    	}
    	immap->im_ioport.iop_pcdir |= 0x0400;
    	immap->im_ioport.iop_padir |= 0x0200;
    #if 0
    	/*  VCC switch error flag, PCMCIA slot INPACK_ pin */
    	cp->cp_pbdir &= ~(0x0020 | 0x0010);
    	cp->cp_pbpar &= ~(0x0020 | 0x0010);
    	udelay(500000);
    #endif
    	debug ("Enable PCMCIA buffers and stop RESET\n");
    	reg  =  PCMCIA_PGCRX(_slot_);
    	reg &= ~__MY_PCMCIA_GCRX_CXRESET;	/* active high */
    	reg &= ~__MY_PCMCIA_GCRX_CXOE;		/* active low  */
    	PCMCIA_PGCRX(_slot_) = reg;
    
    	udelay(250000);	/* some cards need >150 ms to come up :-( */
    
    	debug ("# hardware_enable done\n");
    
    	return (0);
    }
    
    
    #if (CONFIG_COMMANDS & CFG_CMD_PCMCIA)
    static int hardware_disable(int slot)
    {
    	volatile immap_t	*immap;
    	volatile pcmconf8xx_t	*pcmp;
    	u_long reg;
    
    	debug ("hardware_disable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot);
    
    	immap = (immap_t *)CFG_IMMR;
    	pcmp = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia));
    
    	/* remove all power */
    	immap->im_ioport.iop_pcdat |= 0x0400;
    	immap->im_ioport.iop_padat |= 0x0200;
    
    	/* Configure PCMCIA General Control Register */
    	debug ("Disable PCMCIA buffers and assert RESET\n");
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    	reg |= __MY_PCMCIA_GCRX_CXRESET;	/* active high */
    	reg |= __MY_PCMCIA_GCRX_CXOE;		/* active low  */
    	PCMCIA_PGCRX(_slot_) = reg;
    
    	udelay(10000);
    
    	return (0);
    }
    #endif	/* CFG_CMD_PCMCIA */
    
    
    static int voltage_set(int slot, int vcc, int vpp)
    {
    	volatile immap_t	*immap;
    	volatile pcmconf8xx_t	*pcmp;
    	u_long reg;
    
    	debug ("voltage_set: "
    		PCMCIA_BOARD_MSG
    		" Slot %c, Vcc=%d.%d, Vpp=%d.%d\n",
    		'A'+slot, vcc/10, vcc%10, vpp/10, vcc%10);
    
    	immap = (immap_t *)CFG_IMMR;
    	pcmp = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia));
    	/*
    	 * Disable PCMCIA buffers (isolate the interface)
    	 * and assert RESET signal
    	 */
    	debug ("Disable PCMCIA buffers and assert RESET\n");
    
    	reg  = PCMCIA_PGCRX(_slot_);
    	reg |= __MY_PCMCIA_GCRX_CXRESET;	/* active high */
    	reg |= __MY_PCMCIA_GCRX_CXOE;		/* active low  */
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    	PCMCIA_PGCRX(_slot_) = reg;
    	udelay(500);
    
    	/*
    	 * Configure Ports A & C pins for
    	 * 5 Volts Enable and 3 Volts enable,
    	 * Turn off all power
    	 */
    	debug ("PCMCIA power OFF\n");
    	immap->im_ioport.iop_pcpar &= ~(0x0400);
    	immap->im_ioport.iop_pcso  &= ~(0x0400);/*
    	immap->im_ioport.iop_pcdir |= 0x0400;*/
    
    	immap->im_ioport.iop_papar &= ~(0x0200);/*
    	immap->im_ioport.iop_padir |= 0x0200;*/
    
    	immap->im_ioport.iop_pcdat |= 0x0400;
    	immap->im_ioport.iop_padat |= 0x0200;
    
    	reg = 0;
    	switch(vcc) {
    	case  0: 		break;
    	case 33: reg |= 0x0200;	break;
    	case 50: reg |= 0x0400;	break;
    	default: 		goto done;
    	}