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__); } |