uboot/drivers/fpga/spartan2.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2002
   3 * Rich Ireland, Enterasys Networks, rireland@enterasys.com.
   4 *
   5 * See file CREDITS for list of people who contributed to this
   6 * project.
   7 *
   8 * This program is free software; you can redistribute it and/or
   9 * modify it under the terms of the GNU General Public License as
  10 * published by the Free Software Foundation; either version 2 of
  11 * the License, or (at your option) any later version.
  12 *
  13 * This program is distributed in the hope that it will be useful,
  14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 * GNU General Public License for more details.
  17 *
  18 * You should have received a copy of the GNU General Public License
  19 * along with this program; if not, write to the Free Software
  20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  21 * MA 02111-1307 USA
  22 *
  23 */
  24
  25#include <common.h>             /* core U-Boot definitions */
  26#include <spartan2.h>           /* Spartan-II device family */
  27
  28/* Define FPGA_DEBUG to get debug printf's */
  29#ifdef  FPGA_DEBUG
  30#define PRINTF(fmt,args...)     printf (fmt ,##args)
  31#else
  32#define PRINTF(fmt,args...)
  33#endif
  34
  35#undef CONFIG_SYS_FPGA_CHECK_BUSY
  36#undef CONFIG_SYS_FPGA_PROG_FEEDBACK
  37
  38/* Note: The assumption is that we cannot possibly run fast enough to
  39 * overrun the device (the Slave Parallel mode can free run at 50MHz).
  40 * If there is a need to operate slower, define CONFIG_FPGA_DELAY in
  41 * the board config file to slow things down.
  42 */
  43#ifndef CONFIG_FPGA_DELAY
  44#define CONFIG_FPGA_DELAY()
  45#endif
  46
  47#ifndef CONFIG_SYS_FPGA_WAIT
  48#define CONFIG_SYS_FPGA_WAIT CONFIG_SYS_HZ/100  /* 10 ms */
  49#endif
  50
  51static int Spartan2_sp_load(Xilinx_desc *desc, const void *buf, size_t bsize);
  52static int Spartan2_sp_dump(Xilinx_desc *desc, const void *buf, size_t bsize);
  53/* static int Spartan2_sp_info(Xilinx_desc *desc ); */
  54
  55static int Spartan2_ss_load(Xilinx_desc *desc, const void *buf, size_t bsize);
  56static int Spartan2_ss_dump(Xilinx_desc *desc, const void *buf, size_t bsize);
  57/* static int Spartan2_ss_info(Xilinx_desc *desc ); */
  58
  59/* ------------------------------------------------------------------------- */
  60/* Spartan-II Generic Implementation */
  61int Spartan2_load(Xilinx_desc *desc, const void *buf, size_t bsize)
  62{
  63        int ret_val = FPGA_FAIL;
  64
  65        switch (desc->iface) {
  66        case slave_serial:
  67                PRINTF ("%s: Launching Slave Serial Load\n", __FUNCTION__);
  68                ret_val = Spartan2_ss_load (desc, buf, bsize);
  69                break;
  70
  71        case slave_parallel:
  72                PRINTF ("%s: Launching Slave Parallel Load\n", __FUNCTION__);
  73                ret_val = Spartan2_sp_load (desc, buf, bsize);
  74                break;
  75
  76        default:
  77                printf ("%s: Unsupported interface type, %d\n",
  78                                __FUNCTION__, desc->iface);
  79        }
  80
  81        return ret_val;
  82}
  83
  84int Spartan2_dump(Xilinx_desc *desc, const void *buf, size_t bsize)
  85{
  86        int ret_val = FPGA_FAIL;
  87
  88        switch (desc->iface) {
  89        case slave_serial:
  90                PRINTF ("%s: Launching Slave Serial Dump\n", __FUNCTION__);
  91                ret_val = Spartan2_ss_dump (desc, buf, bsize);
  92                break;
  93
  94        case slave_parallel:
  95                PRINTF ("%s: Launching Slave Parallel Dump\n", __FUNCTION__);
  96                ret_val = Spartan2_sp_dump (desc, buf, bsize);
  97                break;
  98
  99        default:
 100                printf ("%s: Unsupported interface type, %d\n",
 101                                __FUNCTION__, desc->iface);
 102        }
 103
 104        return ret_val;
 105}
 106
 107int Spartan2_info( Xilinx_desc *desc )
 108{
 109        return FPGA_SUCCESS;
 110}
 111
 112
 113/* ------------------------------------------------------------------------- */
 114/* Spartan-II Slave Parallel Generic Implementation */
 115
 116static int Spartan2_sp_load(Xilinx_desc *desc, const void *buf, size_t bsize)
 117{
 118        int ret_val = FPGA_FAIL;        /* assume the worst */
 119        Xilinx_Spartan2_Slave_Parallel_fns *fn = desc->iface_fns;
 120
 121        PRINTF ("%s: start with interface functions @ 0x%p\n",
 122                        __FUNCTION__, fn);
 123
 124        if (fn) {
 125                size_t bytecount = 0;
 126                unsigned char *data = (unsigned char *) buf;
 127                int cookie = desc->cookie;      /* make a local copy */
 128                unsigned long ts;               /* timestamp */
 129
 130                PRINTF ("%s: Function Table:\n"
 131                                "ptr:\t0x%p\n"
 132                                "struct: 0x%p\n"
 133                                "pre: 0x%p\n"
 134                                "pgm:\t0x%p\n"
 135                                "init:\t0x%p\n"
 136                                "err:\t0x%p\n"
 137                                "clk:\t0x%p\n"
 138                                "cs:\t0x%p\n"
 139                                "wr:\t0x%p\n"
 140                                "read data:\t0x%p\n"
 141                                "write data:\t0x%p\n"
 142                                "busy:\t0x%p\n"
 143                                "abort:\t0x%p\n",
 144                                "post:\t0x%p\n\n",
 145                                __FUNCTION__, &fn, fn, fn->pre, fn->pgm, fn->init, fn->err,
 146                                fn->clk, fn->cs, fn->wr, fn->rdata, fn->wdata, fn->busy,
 147                                fn->abort, fn->post);
 148
 149                /*
 150                 * This code is designed to emulate the "Express Style"
 151                 * Continuous Data Loading in Slave Parallel Mode for
 152                 * the Spartan-II Family.
 153                 */
 154#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
 155                printf ("Loading FPGA Device %d...\n", cookie);
 156#endif
 157                /*
 158                 * Run the pre configuration function if there is one.
 159                 */
 160                if (*fn->pre) {
 161                        (*fn->pre) (cookie);
 162                }
 163
 164                /* Establish the initial state */
 165                (*fn->pgm) (TRUE, TRUE, cookie);        /* Assert the program, commit */
 166
 167                /* Get ready for the burn */
 168                CONFIG_FPGA_DELAY ();
 169                (*fn->pgm) (FALSE, TRUE, cookie);       /* Deassert the program, commit */
 170
 171                ts = get_timer (0);             /* get current time */
 172                /* Now wait for INIT and BUSY to go high */
 173                do {
 174                        CONFIG_FPGA_DELAY ();
 175                        if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) {    /* check the time */
 176                                puts ("** Timeout waiting for INIT to clear.\n");
 177                                (*fn->abort) (cookie);  /* abort the burn */
 178                                return FPGA_FAIL;
 179                        }
 180                } while ((*fn->init) (cookie) && (*fn->busy) (cookie));
 181
 182                (*fn->wr) (TRUE, TRUE, cookie); /* Assert write, commit */
 183                (*fn->cs) (TRUE, TRUE, cookie); /* Assert chip select, commit */
 184                (*fn->clk) (TRUE, TRUE, cookie);        /* Assert the clock pin */
 185
 186                /* Load the data */
 187                while (bytecount < bsize) {
 188                        /* XXX - do we check for an Ctrl-C press in here ??? */
 189                        /* XXX - Check the error bit? */
 190
 191                        (*fn->wdata) (data[bytecount++], TRUE, cookie); /* write the data */
 192                        CONFIG_FPGA_DELAY ();
 193                        (*fn->clk) (FALSE, TRUE, cookie);       /* Deassert the clock pin */
 194                        CONFIG_FPGA_DELAY ();
 195                        (*fn->clk) (TRUE, TRUE, cookie);        /* Assert the clock pin */
 196
 197#ifdef CONFIG_SYS_FPGA_CHECK_BUSY
 198                        ts = get_timer (0);     /* get current time */
 199                        while ((*fn->busy) (cookie)) {
 200                                /* XXX - we should have a check in here somewhere to
 201                                 * make sure we aren't busy forever... */
 202
 203                                CONFIG_FPGA_DELAY ();
 204                                (*fn->clk) (FALSE, TRUE, cookie);       /* Deassert the clock pin */
 205                                CONFIG_FPGA_DELAY ();
 206                                (*fn->clk) (TRUE, TRUE, cookie);        /* Assert the clock pin */
 207
 208                                if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) {    /* check the time */
 209                                        puts ("** Timeout waiting for BUSY to clear.\n");
 210                                        (*fn->abort) (cookie);  /* abort the burn */
 211                                        return FPGA_FAIL;
 212                                }
 213                        }
 214#endif
 215
 216#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
 217                        if (bytecount % (bsize / 40) == 0)
 218                                putc ('.');             /* let them know we are alive */
 219#endif
 220                }
 221
 222                CONFIG_FPGA_DELAY ();
 223                (*fn->cs) (FALSE, TRUE, cookie);        /* Deassert the chip select */
 224                (*fn->wr) (FALSE, TRUE, cookie);        /* Deassert the write pin */
 225
 226#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
 227                putc ('\n');                    /* terminate the dotted line */
 228#endif
 229
 230                /* now check for done signal */
 231                ts = get_timer (0);             /* get current time */
 232                ret_val = FPGA_SUCCESS;
 233                while ((*fn->done) (cookie) == FPGA_FAIL) {
 234
 235                        CONFIG_FPGA_DELAY ();
 236                        (*fn->clk) (FALSE, TRUE, cookie);       /* Deassert the clock pin */
 237                        CONFIG_FPGA_DELAY ();
 238                        (*fn->clk) (TRUE, TRUE, cookie);        /* Assert the clock pin */
 239
 240                        if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) {    /* check the time */
 241                                puts ("** Timeout waiting for DONE to clear.\n");
 242                                (*fn->abort) (cookie);  /* abort the burn */
 243                                ret_val = FPGA_FAIL;
 244                                break;
 245                        }
 246                }
 247
 248                /*
 249                 * Run the post configuration function if there is one.
 250                 */
 251                if (*fn->post)
 252                        (*fn->post) (cookie);
 253
 254#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
 255                if (ret_val == FPGA_SUCCESS)
 256                        puts ("Done.\n");
 257                else
 258                        puts ("Fail.\n");
 259#endif
 260
 261        } else {
 262                printf ("%s: NULL Interface function table!\n", __FUNCTION__);
 263        }
 264
 265        return ret_val;
 266}
 267
 268static int Spartan2_sp_dump(Xilinx_desc *desc, const void *buf, size_t bsize)
 269{
 270        int ret_val = FPGA_FAIL;        /* assume the worst */
 271        Xilinx_Spartan2_Slave_Parallel_fns *fn = desc->iface_fns;
 272
 273        if (fn) {
 274                unsigned char *data = (unsigned char *) buf;
 275                size_t bytecount = 0;
 276                int cookie = desc->cookie;      /* make a local copy */
 277
 278                printf ("Starting Dump of FPGA Device %d...\n", cookie);
 279
 280                (*fn->cs) (TRUE, TRUE, cookie); /* Assert chip select, commit */
 281                (*fn->clk) (TRUE, TRUE, cookie);        /* Assert the clock pin */
 282
 283                /* dump the data */
 284                while (bytecount < bsize) {
 285                        /* XXX - do we check for an Ctrl-C press in here ??? */
 286
 287                        (*fn->clk) (FALSE, TRUE, cookie);       /* Deassert the clock pin */
 288                        (*fn->clk) (TRUE, TRUE, cookie);        /* Assert the clock pin */
 289                        (*fn->rdata) (&(data[bytecount++]), cookie);    /* read the data */
 290#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
 291                        if (bytecount % (bsize / 40) == 0)
 292                                putc ('.');             /* let them know we are alive */
 293#endif
 294                }
 295
 296                (*fn->cs) (FALSE, FALSE, cookie);       /* Deassert the chip select */
 297                (*fn->clk) (FALSE, TRUE, cookie);       /* Deassert the clock pin */
 298                (*fn->clk) (TRUE, TRUE, cookie);        /* Assert the clock pin */
 299
 300#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
 301                putc ('\n');                    /* terminate the dotted line */
 302#endif
 303                puts ("Done.\n");
 304
 305                /* XXX - checksum the data? */
 306        } else {
 307                printf ("%s: NULL Interface function table!\n", __FUNCTION__);
 308        }
 309
 310        return ret_val;
 311}
 312
 313
 314/* ------------------------------------------------------------------------- */
 315
 316static int Spartan2_ss_load(Xilinx_desc *desc, const void *buf, size_t bsize)
 317{
 318        int ret_val = FPGA_FAIL;        /* assume the worst */
 319        Xilinx_Spartan2_Slave_Serial_fns *fn = desc->iface_fns;
 320        int i;
 321        unsigned char val;
 322
 323        PRINTF ("%s: start with interface functions @ 0x%p\n",
 324                        __FUNCTION__, fn);
 325
 326        if (fn) {
 327                size_t bytecount = 0;
 328                unsigned char *data = (unsigned char *) buf;
 329                int cookie = desc->cookie;      /* make a local copy */
 330                unsigned long ts;               /* timestamp */
 331
 332                PRINTF ("%s: Function Table:\n"
 333                                "ptr:\t0x%p\n"
 334                                "struct: 0x%p\n"
 335                                "pgm:\t0x%p\n"
 336                                "init:\t0x%p\n"
 337                                "clk:\t0x%p\n"
 338                                "wr:\t0x%p\n"
 339                                "done:\t0x%p\n\n",
 340                                __FUNCTION__, &fn, fn, fn->pgm, fn->init,
 341                                fn->clk, fn->wr, fn->done);
 342#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
 343                printf ("Loading FPGA Device %d...\n", cookie);
 344#endif
 345
 346                /*
 347                 * Run the pre configuration function if there is one.
 348                 */
 349                if (*fn->pre) {
 350                        (*fn->pre) (cookie);
 351                }
 352
 353                /* Establish the initial state */
 354                (*fn->pgm) (TRUE, TRUE, cookie);        /* Assert the program, commit */
 355
 356                /* Wait for INIT state (init low)                            */
 357                ts = get_timer (0);             /* get current time */
 358                do {
 359                        CONFIG_FPGA_DELAY ();
 360                        if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) {    /* check the time */
 361                                puts ("** Timeout waiting for INIT to start.\n");
 362                                return FPGA_FAIL;
 363                        }
 364                } while (!(*fn->init) (cookie));
 365
 366                /* Get ready for the burn */
 367                CONFIG_FPGA_DELAY ();
 368                (*fn->pgm) (FALSE, TRUE, cookie);       /* Deassert the program, commit */
 369
 370                ts = get_timer (0);             /* get current time */
 371                /* Now wait for INIT to go high */
 372                do {
 373                        CONFIG_FPGA_DELAY ();
 374                        if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) {    /* check the time */
 375                                puts ("** Timeout waiting for INIT to clear.\n");
 376                                return FPGA_FAIL;
 377                        }
 378                } while ((*fn->init) (cookie));
 379
 380                /* Load the data */
 381                while (bytecount < bsize) {
 382
 383                        /* Xilinx detects an error if INIT goes low (active)
 384                           while DONE is low (inactive) */
 385                        if ((*fn->done) (cookie) == 0 && (*fn->init) (cookie)) {
 386                                puts ("** CRC error during FPGA load.\n");
 387                                return (FPGA_FAIL);
 388                        }
 389                        val = data [bytecount ++];
 390                        i = 8;
 391                        do {
 392                                /* Deassert the clock */
 393                                (*fn->clk) (FALSE, TRUE, cookie);
 394                                CONFIG_FPGA_DELAY ();
 395                                /* Write data */
 396                                (*fn->wr) ((val & 0x80), TRUE, cookie);
 397                                CONFIG_FPGA_DELAY ();
 398                                /* Assert the clock */
 399                                (*fn->clk) (TRUE, TRUE, cookie);
 400                                CONFIG_FPGA_DELAY ();
 401                                val <<= 1;
 402                                i --;
 403                        } while (i > 0);
 404
 405#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
 406                        if (bytecount % (bsize / 40) == 0)
 407                                putc ('.');             /* let them know we are alive */
 408#endif
 409                }
 410
 411                CONFIG_FPGA_DELAY ();
 412
 413#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
 414                putc ('\n');                    /* terminate the dotted line */
 415#endif
 416
 417                /* now check for done signal */
 418                ts = get_timer (0);             /* get current time */
 419                ret_val = FPGA_SUCCESS;
 420                (*fn->wr) (TRUE, TRUE, cookie);
 421
 422                while (! (*fn->done) (cookie)) {
 423
 424                        CONFIG_FPGA_DELAY ();
 425                        (*fn->clk) (FALSE, TRUE, cookie);       /* Deassert the clock pin */
 426                        CONFIG_FPGA_DELAY ();
 427                        (*fn->clk) (TRUE, TRUE, cookie);        /* Assert the clock pin */
 428
 429                        putc ('*');
 430
 431                        if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) {    /* check the time */
 432                                puts ("** Timeout waiting for DONE to clear.\n");
 433                                ret_val = FPGA_FAIL;
 434                                break;
 435                        }
 436                }
 437                putc ('\n');                    /* terminate the dotted line */
 438
 439                /*
 440                 * Run the post configuration function if there is one.
 441                 */
 442                if (*fn->post)
 443                        (*fn->post) (cookie);
 444
 445#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
 446                if (ret_val == FPGA_SUCCESS)
 447                        puts ("Done.\n");
 448                else
 449                        puts ("Fail.\n");
 450#endif
 451
 452        } else {
 453                printf ("%s: NULL Interface function table!\n", __FUNCTION__);
 454        }
 455
 456        return ret_val;
 457}
 458
 459static int Spartan2_ss_dump(Xilinx_desc *desc, const void *buf, size_t bsize)
 460{
 461        /* Readback is only available through the Slave Parallel and         */
 462        /* boundary-scan interfaces.                                         */
 463        printf ("%s: Slave Serial Dumping is unavailable\n",
 464                        __FUNCTION__);
 465        return FPGA_FAIL;
 466}
 467