diff options
Diffstat (limited to 'drivers/pcmcia/mpc8xx_pcmcia.c')
| -rw-r--r-- | drivers/pcmcia/mpc8xx_pcmcia.c | 304 | 
1 files changed, 304 insertions, 0 deletions
| diff --git a/drivers/pcmcia/mpc8xx_pcmcia.c b/drivers/pcmcia/mpc8xx_pcmcia.c new file mode 100644 index 000000000..8a34cd305 --- /dev/null +++ b/drivers/pcmcia/mpc8xx_pcmcia.c @@ -0,0 +1,304 @@ +#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 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	/* 0 */ + +#endif	/* CONFIG_8xx && CONFIG_PCMCIA */ |