diff options
Diffstat (limited to 'common')
| -rw-r--r-- | common/cmd_fdc.c | 49 | ||||
| -rw-r--r-- | common/devices.c | 5 | ||||
| -rw-r--r-- | common/spartan2.c | 199 | 
3 files changed, 231 insertions, 22 deletions
| diff --git a/common/cmd_fdc.c b/common/cmd_fdc.c index 712c14b57..8e6b7350c 100644 --- a/common/cmd_fdc.c +++ b/common/cmd_fdc.c @@ -173,19 +173,35 @@ const static FD_GEO_STRUCT floppy_type[2] = {  static FDC_COMMAND_STRUCT cmd; /* global command struct */ +/* If the boot drive number is undefined, we assume it's drive 0             */ +#ifndef CFG_FDC_DRIVE_NUMBER +#define CFG_FDC_DRIVE_NUMBER 0 +#endif + +/* Hardware access */ +#ifndef CFG_ISA_IO_STRIDE +#define CFG_ISA_IO_STRIDE 1 +#endif + +#ifndef CFG_ISA_IO_OFFSET +#define CFG_ISA_IO_OFFSET 0 +#endif + +  /* Supporting Functions */  /* reads a Register of the FDC */  unsigned char read_fdc_reg(unsigned int addr)  { -	volatile unsigned char *val = (volatile unsigned char *)(CFG_ISA_IO_BASE_ADDRESS | addr); -	return val[0]; +	volatile unsigned char *val = (volatile unsigned char *)(CFG_ISA_IO_BASE_ADDRESS + (addr * CFG_ISA_IO_STRIDE) + CFG_ISA_IO_OFFSET); +         +	return val [0];  }  /* writes a Register of the FDC */  void write_fdc_reg(unsigned int addr, unsigned char val)  { -		volatile unsigned char *tmp = (volatile unsigned char *)(CFG_ISA_IO_BASE_ADDRESS | addr); -		tmp[0]=val; +        volatile unsigned char *tmp = (volatile unsigned char *)(CFG_ISA_IO_BASE_ADDRESS + (addr * CFG_ISA_IO_STRIDE) + CFG_ISA_IO_OFFSET); +	tmp[0]=val;  }  /* waits for an interrupt (polling) */ @@ -263,7 +279,8 @@ int fdc_issue_cmd(FDC_COMMAND_STRUCT *pCMD,FD_GEO_STRUCT *pFG)  	head = sect / pFG->sect; /* head nr */  	sect =  sect % pFG->sect; /* remaining blocks */  	sect++; /* sectors are 1 based */ -	PRINTF("Track %ld, Head %ld, Sector %ld, Drive %d (blnr %ld)\n",track,head,sect,pCMD->drive,pCMD->blnr); +	PRINTF("Cmd 0x%02x Track %ld, Head %ld, Sector %ld, Drive %d (blnr %ld)\n",pCMD->cmd[0],track,head,sect,pCMD->drive,pCMD->blnr); +  	if(head|=0) { /* max heads = 2 */  		pCMD->cmd[DRIVE]=pCMD->drive | 0x04; /* head 1 */  		pCMD->cmd[HEAD]=(unsigned char) head; /* head register */ @@ -538,20 +555,20 @@ int fdc_check_drive(FDC_COMMAND_STRUCT *pCMD, FD_GEO_STRUCT *pFG)  		select_fdc_drive(pCMD);  		pCMD->blnr=0; /* set to the 1st block */  		if(fdc_recalibrate(pCMD,pFG)==FALSE) -			break; +			continue;  		if((pCMD->result[STATUS_0]&0x10)==0x10) -			break; +			continue;  		/* ok drive connected check for disk */  		state|=(1<<drives);  		pCMD->blnr=pFG->size; /* set to the last block */  		if(fdc_seek(pCMD,pFG)==FALSE) -			break; +			continue;  		pCMD->blnr=0; /* set to the 1st block */  		if(fdc_recalibrate(pCMD,pFG)==FALSE) -			break; +			continue;  		pCMD->cmd[COMMAND]=FDC_CMD_READ_ID;  		if(fdc_issue_cmd(pCMD,pFG)==FALSE) -			break; +			continue;  		state|=(0x10<<drives);  	}  	stop_fdc_drive(pCMD); @@ -575,12 +592,16 @@ int fdc_setup(FDC_COMMAND_STRUCT *pCMD,	FD_GEO_STRUCT *pFG)  {  	int i; + +#ifdef CFG_FDC_HW_INIT +        fdc_hw_init (); +#endif  	/* first, we reset the FDC via the DOR */  	write_fdc_reg(FDC_DOR,0x00);  	for(i=0; i<255; i++) /* then we wait some time */  		udelay(500);  	/* then, we clear the reset in the DOR */ -	pCMD->drive=0; +	pCMD->drive=CFG_FDC_DRIVE_NUMBER;  	select_fdc_drive(pCMD);  	/* initialize the CCR */  	write_fdc_reg(FDC_CCR,pFG->rate); @@ -602,7 +623,7 @@ int fdc_setup(FDC_COMMAND_STRUCT *pCMD,	FD_GEO_STRUCT *pFG)  	}  	/* assuming drive 0 for rest of configuration  	 * issue the configure command */ -	pCMD->drive=0; +	pCMD->drive=CFG_FDC_DRIVE_NUMBER;  	select_fdc_drive(pCMD);  	pCMD->cmd[COMMAND]=FDC_CMD_CONFIGURE;  	if(fdc_issue_cmd(pCMD,pFG)==FALSE) { @@ -641,11 +662,11 @@ int do_fdcboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])  	switch (argc) {  	case 1:  		addr = CFG_LOAD_ADDR; -		boot_drive=0; /* default boot from drive 0 */ +		boot_drive=CFG_FDC_DRIVE_NUMBER;   		break;  	case 2:  		addr = simple_strtoul(argv[1], NULL, 16); -		boot_drive=0; /* default boot from drive 0 */ +		boot_drive=CFG_FDC_DRIVE_NUMBER;  		break;  	case 3:  		addr = simple_strtoul(argv[1], NULL, 16); diff --git a/common/devices.c b/common/devices.c index 8207f834f..7489eac41 100644 --- a/common/devices.c +++ b/common/devices.c @@ -26,7 +26,12 @@  #include <stdarg.h>  #include <malloc.h>  #include <devices.h> +#ifdef CONFIG_LOGBUFFER +#include <logbuff.h> +#endif +#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C)  #include <i2c.h> +#endif  list_t devlist = 0;  device_t *stdio_devices[] = { NULL, NULL, NULL }; diff --git a/common/spartan2.c b/common/spartan2.c index 9ac1e1377..dcda0c494 100644 --- a/common/spartan2.c +++ b/common/spartan2.c @@ -35,7 +35,7 @@  #endif  #undef CFG_FPGA_CHECK_BUSY -#define CFG_FPGA_PROG_FEEDBACK +#undef CFG_FPGA_PROG_FEEDBACK  /* Note: The assumption is that we cannot possibly run fast enough to   * overrun the device (the Slave Parallel mode can free run at 50MHz). @@ -438,14 +438,150 @@ static int Spartan2_sp_reloc (Xilinx_desc * desc, ulong reloc_offset)  static int Spartan2_ss_load (Xilinx_desc * desc, void *buf, size_t bsize)  { -	printf ("%s: Slave Serial Loading is still unsupported\n", -			__FUNCTION__); -	return FPGA_FAIL; +        int ret_val = FPGA_FAIL;	/* assume the worst */ +	Xilinx_Spartan2_Slave_Serial_fns *fn = desc->iface_fns; +        int i; +        char  val; +         +	PRINTF ("%s: start with interface functions @ 0x%p\n", +			__FUNCTION__, fn); + +	if (fn) { +		size_t bytecount = 0; +		unsigned char *data = (unsigned char *) buf; +		int cookie = desc->cookie;	/* make a local copy */ +		unsigned long ts;		/* timestamp */ + +		PRINTF ("%s: Function Table:\n" +				"ptr:\t0x%p\n" +				"struct: 0x%p\n" +				"pgm:\t0x%p\n" +				"init:\t0x%p\n" +				"clk:\t0x%p\n" +				"wr:\t0x%p\n" +				"done:\t0x%p\n\n", +				__FUNCTION__, &fn, fn, fn->pgm, fn->init,  +				fn->clk, fn->wr, fn->done);  +#ifdef CFG_FPGA_PROG_FEEDBACK +		printf ("Loading FPGA Device %d...\n", cookie); +#endif + +		/* +		 * Run the pre configuration function if there is one. +		 */ +		if (*fn->pre) { +			(*fn->pre) (cookie); +		} + +		/* Establish the initial state */ +		(*fn->pgm) (TRUE, TRUE, cookie);	/* Assert the program, commit */ + +                /* Wait for INIT state (init low)                            */ +		ts = get_timer (0);		/* get current time */ +		do { +			CONFIG_FPGA_DELAY (); +			if (get_timer (ts) > CFG_FPGA_WAIT) {	/* check the time */ +				puts ("** Timeout waiting for INIT to start.\n"); +				return FPGA_FAIL; +			} +		} while (!(*fn->init) (cookie)); +                 +		/* Get ready for the burn */ +		CONFIG_FPGA_DELAY (); +		(*fn->pgm) (FALSE, TRUE, cookie);	/* Deassert the program, commit */ + +		ts = get_timer (0);		/* get current time */ +		/* Now wait for INIT to go high */ +		do { +			CONFIG_FPGA_DELAY (); +			if (get_timer (ts) > CFG_FPGA_WAIT) {	/* check the time */ +				puts ("** Timeout waiting for INIT to clear.\n"); +				return FPGA_FAIL; +			} +		} while ((*fn->init) (cookie)); + +		/* Load the data */ +		while (bytecount < bsize) { +                     +                        /* Xilinx detects an error if INIT goes low (active) +                           while DONE is low (inactive) */ +                        if ((*fn->done) (cookie) == 0 && (*fn->init) (cookie)) { +                                puts ("** CRC error during FPGA load.\n"); +                                return (FPGA_FAIL); +                        } +                        val = data [bytecount ++]; +                        i = 8; +                        do { +                                /* Deassert the clock */ +                                (*fn->clk) (FALSE, TRUE, cookie); +                                CONFIG_FPGA_DELAY (); +                                /* Write data */ +                                (*fn->wr) ((val < 0), TRUE, cookie); +                                CONFIG_FPGA_DELAY (); +                                /* Assert the clock */ +                                (*fn->clk) (TRUE, TRUE, cookie); +                                CONFIG_FPGA_DELAY (); +                                val <<= 1; +                                i --; +                        } while (i > 0); +                         +#ifdef CFG_FPGA_PROG_FEEDBACK +			if (bytecount % (bsize / 40) == 0) +				putc ('.');		/* let them know we are alive */ +#endif +		} + +		CONFIG_FPGA_DELAY (); + +#ifdef CFG_FPGA_PROG_FEEDBACK +		putc ('\n');			/* terminate the dotted line */ +#endif + +		/* now check for done signal */ +		ts = get_timer (0);		/* get current time */ +		ret_val = FPGA_SUCCESS; +                (*fn->wr) (TRUE, TRUE, cookie); + +		while (! (*fn->done) (cookie)) { +			/* XXX - we should have a check in here somewhere to +			 * make sure we aren't busy forever... */ + +			CONFIG_FPGA_DELAY (); +			(*fn->clk) (FALSE, TRUE, cookie);	/* Deassert the clock pin */ +			CONFIG_FPGA_DELAY (); +			(*fn->clk) (TRUE, TRUE, cookie);	/* Assert the clock pin */ + +                        putc ('*'); +                         +			if (get_timer (ts) > CFG_FPGA_WAIT) {	/* check the time */ +				puts ("** Timeout waiting for DONE to clear.\n"); +				ret_val = FPGA_FAIL; +				break; +			} +		} +		putc ('\n');			/* terminate the dotted line */ + +#ifdef CFG_FPGA_PROG_FEEDBACK +		if (ret_val == FPGA_SUCCESS) { +			puts ("Done.\n"); +		} +		else { +			puts ("Fail.\n"); +		} +#endif + +	} else { +		printf ("%s: NULL Interface function table!\n", __FUNCTION__); +	} + +	return ret_val;  }  static int Spartan2_ss_dump (Xilinx_desc * desc, void *buf, size_t bsize)  { -	printf ("%s: Slave Serial Dumping is still unsupported\n", +        /* Readback is only available through the Slave Parallel and         */ +        /* boundary-scan interfaces.                                         */ +	printf ("%s: Slave Serial Dumping is unavailable\n",  			__FUNCTION__);  	return FPGA_FAIL;  } @@ -453,12 +589,59 @@ static int Spartan2_ss_dump (Xilinx_desc * desc, void *buf, size_t bsize)  static int Spartan2_ss_reloc (Xilinx_desc * desc, ulong reloc_offset)  {  	int ret_val = FPGA_FAIL;	/* assume the worst */ -	Xilinx_Spartan2_Slave_Serial_fns *fn = +	Xilinx_Spartan2_Slave_Serial_fns *fn_r, *fn =  			(Xilinx_Spartan2_Slave_Serial_fns *) (desc->iface_fns);  	if (fn) { -		printf ("%s: Slave Serial Loading is still unsupported\n", -				__FUNCTION__); +		ulong addr; + +		/* Get the relocated table address */ +		addr = (ulong) fn + reloc_offset; +		fn_r = (Xilinx_Spartan2_Slave_Serial_fns *) addr; + +		if (!fn_r->relocated) { + +			if (memcmp (fn_r, fn, +						sizeof (Xilinx_Spartan2_Slave_Serial_fns)) +				== 0) { +				/* good copy of the table, fix the descriptor pointer */ +				desc->iface_fns = fn_r; +			} else { +				PRINTF ("%s: Invalid function table at 0x%p\n", +						__FUNCTION__, fn_r); +				return FPGA_FAIL; +			} + +			PRINTF ("%s: Relocating descriptor at 0x%p\n", __FUNCTION__, +					desc); + +			addr = (ulong) (fn->pre) + reloc_offset; +			fn_r->pre = (Xilinx_pre_fn) addr; + +			addr = (ulong) (fn->pgm) + reloc_offset; +			fn_r->pgm = (Xilinx_pgm_fn) addr; + +			addr = (ulong) (fn->init) + reloc_offset; +			fn_r->init = (Xilinx_init_fn) addr; + +			addr = (ulong) (fn->done) + reloc_offset; +			fn_r->done = (Xilinx_done_fn) addr; + +			addr = (ulong) (fn->clk) + reloc_offset; +			fn_r->clk = (Xilinx_clk_fn) addr; + +			addr = (ulong) (fn->wr) + reloc_offset; +			fn_r->wr = (Xilinx_wr_fn) addr; + +			fn_r->relocated = TRUE; + +		} else { +			/* this table has already been moved */ +			/* XXX - should check to see if the descriptor is correct */ +			desc->iface_fns = fn_r; +		} + +		ret_val = FPGA_SUCCESS;  	} else {  		printf ("%s: NULL Interface function table!\n", __FUNCTION__);  	} |