Skip to content
Snippets Groups Projects
cmd_pcmcia.c 78.6 KiB
Newer Older
  • Learn to ignore specific revisions
  • 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 (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[] = {
    	"ARGOSY PnPIDE D5",
    	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;
    	}
    	puts (id_str);
    	putc ('\n');
    
    	for (card=known_cards; *card; ++card) {
    		debug ("## Compare against \"%s\"\n", *card);
    		if (strcmp(*card, id_str) == 0) {	/* found! */
    			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;
    	else
    		immap->im_ioport.iop_padat &= ~mask;
    }
    
    static const unsigned short oc_mask = _BW(8);
    
    static void cfg_oc(void)
    {
    	volatile immap_t *immap = (immap_t *)CFG_IMMR;
    	unsigned short mask = oc_mask;
    
    	immap->im_ioport.iop_pcdir &= ~mask;
    	immap->im_ioport.iop_pcso  &= ~mask;
    	immap->im_ioport.iop_pcint &= ~mask;
    	immap->im_ioport.iop_pcpar &= ~mask;
    }
    
    static int get_oc(void)
    {
    	volatile immap_t *immap = (immap_t *)CFG_IMMR;
    	unsigned short mask = oc_mask;
    	int what;
    
    	what = !!(immap->im_ioport.iop_pcdat & mask);;
    	return what;
    }
    
    static const unsigned short shdn_mask = _BW(12);
    
    static void cfg_shdn(void)
    {
    	volatile immap_t *immap = (immap_t *)CFG_IMMR;
    	unsigned short mask;
    
    	mask = shdn_mask;
    
    	immap->im_ioport.iop_papar &= ~mask;
    	immap->im_ioport.iop_paodr &= ~mask;
    	immap->im_ioport.iop_padir |=  mask;
    }
    
    static void set_shdn(int what)
    {
    	volatile immap_t *immap = (immap_t *)CFG_IMMR;
    	unsigned short mask;
    
    	mask = shdn_mask;
    
    	if (what)
    		immap->im_ioport.iop_padat |= mask;
    	else
    		immap->im_ioport.iop_padat &= ~mask;
    }
    
    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;
    	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 ();
    
    	/* 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(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))) {
    		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");
    
    	if ((pipr & mask) == mask) {
    		set_vppd(0, 1); set_vppd(1, 1); 		/* VAVPP => Hi-Z */
    		set_vccd(0, 0); set_vccd(1, 1); 		/* 5V on, 3V off */
    		puts (" 5.0V card found: ");
    	} else {
    		set_vppd(0, 1); set_vppd(1, 1); 		/* VAVPP => Hi-Z */
    		set_vccd(0, 1); set_vccd(1, 0); 		/* 5V off, 3V on */
    		puts (" 3.3V card found: ");
    	}
    
    	/*  Wait 500 ms; use this to check for over-current */
    	for (i=0; i<5000; ++i) {
    		if (!get_oc()) {
    			printf ("   *** Overcurrent - Safety shutdown ***\n");
    			set_vccd(0, 0); set_vccd(1, 0); 		/* VAVPP => Hi-Z */
    			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 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");
    	reg  = 0;
    	reg |= __MY_PCMCIA_GCRX_CXRESET;	/* active high */
    	reg |= __MY_PCMCIA_GCRX_CXOE;		/* active low  */
    	PCMCIA_PGCRX(_slot_) = reg;
    
    	/* All voltages off / Hi-Z */
    			set_vppd(0, 1); set_vppd(1, 1);
    	set_vccd(0, 1); set_vccd(1, 1);
    
    	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