Skip to content
Snippets Groups Projects
cmd_pcmcia.c 83.4 KiB
Newer Older
  • Learn to ignore specific revisions
  • Wolfgang Denk's avatar
    Wolfgang Denk committed
    	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);
    
    #ifndef CONFIG_HMI10
    
    	if (pcmp->pcmc_pipr & (0x18000000 >> (slot << 4))) {
    
    #else
    	if (pcmp->pcmc_pipr & (0x10000000 >> (slot << 4))) {
    
    #endif	/* CONFIG_HMI10 */
    
    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;
    	}
    
    	/* Checking supported voltages */
    
    	debug ("PIPR: 0x%x --> %s\n",
    		pcmp->pcmc_pipr,
    		(pcmp->pcmc_pipr & 0x00008000) ? "only 5 V" : "can do 3.3V");
    
    	if (reg & 0x0200)
    		immap->im_ioport.iop_pcdat &= !reg;
    	if (reg & 0x0400)
    		immap->im_ioport.iop_padat &= !reg;
    
    	immap->im_ioport.iop_pcdir |= 0x0200;
    	immap->im_ioport.iop_padir |= 0x0400;
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    	if (reg) {
    		debug ("PCMCIA powered at %sV\n",
    			(reg&0x0400) ? "5.0" : "3.3");
    	} 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	/* R360MPI */
    
    
    /* -------------------------------------------------------------------- */
    
    /* KUP4K and KUP4X Boards								*/
    
    /* -------------------------------------------------------------------- */
    
    #if defined(CONFIG_KUP4K) || defined(CONFIG_KUP4X)
    
    #define PCMCIA_BOARD_MSG "KUP"
    
    
    #define KUP4K_PCMCIA_B_3V3 (0x00020000)
    
    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
    
    	 */
    	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(2500);
    
    	if (slot) { /* Slot A is built-in */
    		cp->cp_pbdir |=  KUP4K_PCMCIA_B_3V3;
    		cp->cp_pbpar &= ~KUP4K_PCMCIA_B_3V3;
    		/* remove all power */
    		cp->cp_pbdat |=  KUP4K_PCMCIA_B_3V3; /* active low */
    	}
    
    	/*
    	 * 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))) {
    
    	printf("%s  Slot %c:", slot ? "" : "\n", 'A' + slot);
    
    	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) {
    		puts (" 5.0V card found: NOT SUPPORTED !!!\n");
    	} else {
    
    		if(slot)
    			cp->cp_pbdat &= ~KUP4K_PCMCIA_B_3V3;
    
    		puts (" 3.3V card found: ");
    	}
    #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 &= ~__MY_PCMCIA_GCRX_CXRESET;	/* active high */
    	reg &= ~__MY_PCMCIA_GCRX_CXOE;		/* active low  */
    
    
    	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));
    	cp    = (cpm8xx_t *)(&(((immap_t *)CFG_IMMR)->im_cpm));
    
    	if (slot)
    		cp->cp_pbdat |= KUP4K_PCMCIA_B_3V3;
    
    
    	/* Configure PCMCIA General Control Register */
    	debug ("Disable PCMCIA buffers and assert RESET\n");
    
    	reg |= __MY_PCMCIA_GCRX_CXRESET;	/* active high */
    	reg |= __MY_PCMCIA_GCRX_CXOE;		/* active low  */
    
    
    	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);
    
    
    	if (!slot) /* Slot A is not configurable */
    		return 0;
    
    
    	immap = (immap_t *)CFG_IMMR;
    	pcmp = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia));
    	cp    = (cpm8xx_t *)(&(((immap_t *)CFG_IMMR)->im_cpm));
    
    	/*
    	 * 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  */
    
    	udelay(500);
    
    	debug ("PCMCIA power OFF\n");
    	/*
    	 * Configure Port B pins for
    	 * 3 Volts enable
    	 */
    	cp->cp_pbdir |=  KUP4K_PCMCIA_B_3V3;
    	cp->cp_pbpar &= ~KUP4K_PCMCIA_B_3V3;
    	/* remove all power */
    	cp->cp_pbdat |=  KUP4K_PCMCIA_B_3V3; /* active low */
    
    	switch(vcc) {
    	case  0: 		break;
    	case 33:
    		cp->cp_pbdat &= ~KUP4K_PCMCIA_B_3V3;
    		debug ("PCMCIA powered at 3.3V\n");
    		break;
    	case 50:
    		debug ("PCMCIA: 5Volt vcc not supported\n");
    		break;
    	default:
    		puts("PCMCIA: vcc not supported");
    		break;
    	}
    
    	/* Checking supported voltages */
    
    	debug ("PIPR: 0x%x --> %s\n",
    		pcmp->pcmc_pipr,
    
    		   (pcmp->pcmc_pipr & (0x80000000 >> (slot << 4)))
    
    			? "only 5 V --> NOT SUPPORTED"
    			: "can do 3.3V");
    
    
    	debug ("Enable PCMCIA buffers and stop RESET\n");
    
    	reg &= ~__MY_PCMCIA_GCRX_CXRESET;	/* active high */
    	reg &= ~__MY_PCMCIA_GCRX_CXOE;		/* active low  */
    
    	udelay(500);
    
    	debug ("voltage_set: " PCMCIA_BOARD_MSG " Slot %c, DONE\n",
    		slot+'A');
    	return (0);
    }
    
    
    #endif	/* KUP4K || KUP4X */
    
    /* -------------------------------------------------------------------- */
    /* End of Board Specific Stuff						*/
    /* -------------------------------------------------------------------- */
    
    /* -------------------------------------------------------------------- */
    /* MPC8xx Specific Stuff - should go to MPC8xx directory		*/
    /* -------------------------------------------------------------------- */
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    
    /*
     * 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 };
    
    
    
    /* -------------------------------------------------------------------- */
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    
    
    #if ( ! defined(CONFIG_I82365) && ! defined(CONFIG_PXA_PCMCIA) )
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    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;
    }
    
    
    #endif	/* CONFIG_I82365 */
    
    
    /* -------------------------------------------------------------------- */
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    
    #if 0
    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 0ns
    		 * if not specified by the user.
    		 * They should be 255ns.
    		 */
    
    		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
    
    
    /* -------------------------------------------------------------------- */
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    
    
    #if defined(CONFIG_IDE_8xx_PCCARD) || defined(CONFIG_PXA_PCMCIA)
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    static void print_funcid (int func)
    {
    	puts (indent);
    	switch (func) {
    	case CISTPL_FUNCID_MULTI:
    		puts (" Multi-Function");
    		break;
    	case CISTPL_FUNCID_MEMORY:
    		puts (" Memory");
    		break;
    	case CISTPL_FUNCID_SERIAL:
    		puts (" Serial Port");
    		break;
    	case CISTPL_FUNCID_PARALLEL:
    		puts (" Parallel Port");
    		break;
    	case CISTPL_FUNCID_FIXED:
    		puts (" Fixed Disk");
    		break;
    	case CISTPL_FUNCID_VIDEO:
    		puts (" Video Adapter");
    		break;
    	case CISTPL_FUNCID_NETWORK:
    		puts (" Network Adapter");
    		break;
    	case CISTPL_FUNCID_AIMS:
    		puts (" AIMS Card");
    		break;
    	case CISTPL_FUNCID_SCSI:
    		puts (" SCSI Adapter");
    		break;
    	default:
    		puts (" Unknown");
    		break;
    	}
    	puts (" Card\n");
    }
    #endif	/* CONFIG_IDE_8xx_PCCARD */
    
    
    /* -------------------------------------------------------------------- */
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    
    
    #if defined(CONFIG_IDE_8xx_PCCARD) || defined(CONFIG_PXA_PCMCIA)
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    static void print_fixed (volatile uchar *p)
    {
    	if (p == NULL)
    		return;
    
    	puts(indent);
    
    	switch (*p) {
    	case CISTPL_FUNCE_IDE_IFACE:
    	    {   uchar iface = *(p+2);
    
    		puts ((iface == CISTPL_IDE_INTERFACE) ? " IDE" : " unknown");
    		puts (" interface ");
    		break;
    	    }
    	case CISTPL_FUNCE_IDE_MASTER:
    	case CISTPL_FUNCE_IDE_SLAVE:
    	    {   uchar f1 = *(p+2);
    		uchar f2 = *(p+4);
    
    		puts ((f1 & CISTPL_IDE_SILICON) ? " [silicon]" : " [rotating]");
    
    		if (f1 & CISTPL_IDE_UNIQUE)
    			puts (" [unique]");
    
    		puts ((f1 & CISTPL_IDE_DUAL) ? " [dual]" : " [single]");
    
    		if (f2 & CISTPL_IDE_HAS_SLEEP)
    			puts (" [sleep]");
    
    		if (f2 & CISTPL_IDE_HAS_STANDBY)
    			puts (" [standby]");
    
    		if (f2 & CISTPL_IDE_HAS_IDLE)
    			puts (" [idle]");
    
    		if (f2 & CISTPL_IDE_LOW_POWER)
    			puts (" [low power]");
    
    		if (f2 & CISTPL_IDE_REG_INHIBIT)
    			puts (" [reg inhibit]");
    
    		if (f2 & CISTPL_IDE_HAS_INDEX)
    			puts (" [index]");
    
    		if (f2 & CISTPL_IDE_IOIS16)
    			puts (" [IOis16]");
    
    		break;
    	    }
    	}
    	putc ('\n');
    }
    #endif	/* CONFIG_IDE_8xx_PCCARD */
    
    
    /* -------------------------------------------------------------------- */
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    
    
    #if defined(CONFIG_IDE_8xx_PCCARD) || defined(CONFIG_PXA_PCMCIA)
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    
    #define MAX_IDENT_CHARS		64
    #define	MAX_IDENT_FIELDS	4
    
    static uchar *known_cards[] = {
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    	(uchar *)"ARGOSY PnPIDE D5",
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    	NULL
    };
    
    static int identify  (volatile uchar *p)
    {
    	uchar id_str[MAX_IDENT_CHARS];
    	uchar data;
    	uchar *t;
    	uchar **card;
    	int i, done;
    
    	if (p == NULL)
    		return (0);	/* Don't know */
    
    	t = id_str;
    	done =0;
    
    	for (i=0; i<=4 && !done; ++i, p+=2) {
    		while ((data = *p) != '\0') {
    			if (data == 0xFF) {
    				done = 1;
    				break;
    			}
    			*t++ = data;
    			if (t == &id_str[MAX_IDENT_CHARS-1]) {
    				done = 1;
    				break;
    			}
    			p += 2;
    		}
    		if (!done)
    			*t++ = ' ';
    	}
    	*t = '\0';
    	while (--t > id_str) {
    		if (*t == ' ')
    			*t = '\0';
    		else
    			break;
    	}
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    	puts ((char *)id_str);
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    	putc ('\n');
    
    	for (card=known_cards; *card; ++card) {
    		debug ("## Compare against \"%s\"\n", *card);
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    		if (strcmp((char *)*card, (char *)id_str) == 0) {	/* found! */
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    			debug ("## CARD FOUND ##\n");
    			return (1);
    		}
    	}
    
    	return (0);	/* don't know */
    }
    #endif	/* CONFIG_IDE_8xx_PCCARD */
    
    
    /* -------------------------------------------------------------------- */
    /* NETTA board by Intracom S.A.						*/
    /* -------------------------------------------------------------------- */
    
    #if defined(CONFIG_NETTA)
    
    /* some sane bit macros */
    #define _BD(_b)				(1U << (31-(_b)))
    #define _BDR(_l, _h)			(((((1U << (31-(_l))) - 1) << 1) | 1) & ~((1U << (31-(_h))) - 1))
    
    #define _BW(_b)				(1U << (15-(_b)))
    #define _BWR(_l, _h)			(((((1U << (15-(_l))) - 1) << 1) | 1) & ~((1U << (15-(_h))) - 1))
    
    #define _BB(_b)				(1U << (7-(_b)))
    #define _BBR(_l, _h)			(((((1U << (7-(_l))) - 1) << 1) | 1) & ~((1U << (7-(_h))) - 1))
    
    #define _B(_b)				_BD(_b)
    #define _BR(_l, _h)			_BDR(_l, _h)
    
    #define PCMCIA_BOARD_MSG "NETTA"
    
    static const unsigned short vppd_masks[2] = { _BW(14), _BW(15) };
    
    static void cfg_vppd(int no)
    {
    	volatile immap_t *immap = (immap_t *)CFG_IMMR;
    	unsigned short mask;
    
    	if ((unsigned int)no >= sizeof(vppd_masks)/sizeof(vppd_masks[0]))
    		return;
    
    	mask = vppd_masks[no];
    
    	immap->im_ioport.iop_papar &= ~mask;
    	immap->im_ioport.iop_paodr &= ~mask;
    	immap->im_ioport.iop_padir |=  mask;
    }
    
    static void set_vppd(int no, int what)
    {
    	volatile immap_t *immap = (immap_t *)CFG_IMMR;
    	unsigned short mask;
    
    	if ((unsigned int)no >= sizeof(vppd_masks)/sizeof(vppd_masks[0]))
    		return;
    
    	mask = vppd_masks[no];
    
    	if (what)
    		immap->im_ioport.iop_padat |= mask;
    	else
    		immap->im_ioport.iop_padat &= ~mask;
    }
    
    static const unsigned short vccd_masks[2] = { _BW(10), _BW(6) };
    
    static void cfg_vccd(int no)
    {
    	volatile immap_t *immap = (immap_t *)CFG_IMMR;
    	unsigned short mask;
    
    	if ((unsigned int)no >= sizeof(vccd_masks)/sizeof(vccd_masks[0]))
    		return;
    
    	mask = vccd_masks[no];
    
    	immap->im_ioport.iop_papar &= ~mask;
    	immap->im_ioport.iop_paodr &= ~mask;
    	immap->im_ioport.iop_padir |=  mask;
    }
    
    static void set_vccd(int no, int what)
    {
    	volatile immap_t *immap = (immap_t *)CFG_IMMR;
    	unsigned short mask;
    
    	if ((unsigned int)no >= sizeof(vccd_masks)/sizeof(vccd_masks[0]))
    		return;
    
    	mask = vccd_masks[no];
    
    	if (what)
    		immap->im_ioport.iop_padat |= mask;