uboot/drivers/fpga/ACEX1K.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2003
   3 * Steven Scholz, imc Measurement & Control, steven.scholz@imc-berlin.de
   4 *
   5 * (C) Copyright 2002
   6 * Rich Ireland, Enterasys Networks, rireland@enterasys.com.
   7 *
   8 * SPDX-License-Identifier:     GPL-2.0+
   9 */
  10
  11#include <common.h>             /* core U-Boot definitions */
  12#include <ACEX1K.h>             /* ACEX device family */
  13
  14/* Define FPGA_DEBUG to get debug printf's */
  15#ifdef  FPGA_DEBUG
  16#define PRINTF(fmt,args...)     printf (fmt ,##args)
  17#else
  18#define PRINTF(fmt,args...)
  19#endif
  20
  21/* Note: The assumption is that we cannot possibly run fast enough to
  22 * overrun the device (the Slave Parallel mode can free run at 50MHz).
  23 * If there is a need to operate slower, define CONFIG_FPGA_DELAY in
  24 * the board config file to slow things down.
  25 */
  26#ifndef CONFIG_FPGA_DELAY
  27#define CONFIG_FPGA_DELAY()
  28#endif
  29
  30#ifndef CONFIG_SYS_FPGA_WAIT
  31#define CONFIG_SYS_FPGA_WAIT CONFIG_SYS_HZ/10           /* 100 ms */
  32#endif
  33
  34static int ACEX1K_ps_load(Altera_desc *desc, const void *buf, size_t bsize);
  35static int ACEX1K_ps_dump(Altera_desc *desc, const void *buf, size_t bsize);
  36/* static int ACEX1K_ps_info(Altera_desc *desc); */
  37
  38/* ------------------------------------------------------------------------- */
  39/* ACEX1K Generic Implementation */
  40int ACEX1K_load(Altera_desc *desc, const void *buf, size_t bsize)
  41{
  42        int ret_val = FPGA_FAIL;
  43
  44        switch (desc->iface) {
  45        case passive_serial:
  46                PRINTF ("%s: Launching Passive Serial Loader\n", __FUNCTION__);
  47                ret_val = ACEX1K_ps_load (desc, buf, bsize);
  48                break;
  49
  50                /* Add new interface types here */
  51
  52        default:
  53                printf ("%s: Unsupported interface type, %d\n",
  54                                __FUNCTION__, desc->iface);
  55        }
  56
  57        return ret_val;
  58}
  59
  60int ACEX1K_dump(Altera_desc *desc, const void *buf, size_t bsize)
  61{
  62        int ret_val = FPGA_FAIL;
  63
  64        switch (desc->iface) {
  65        case passive_serial:
  66                PRINTF ("%s: Launching Passive Serial Dump\n", __FUNCTION__);
  67                ret_val = ACEX1K_ps_dump (desc, buf, bsize);
  68                break;
  69
  70                /* Add new interface types here */
  71
  72        default:
  73                printf ("%s: Unsupported interface type, %d\n",
  74                                __FUNCTION__, desc->iface);
  75        }
  76
  77        return ret_val;
  78}
  79
  80int ACEX1K_info( Altera_desc *desc )
  81{
  82        return FPGA_SUCCESS;
  83}
  84
  85
  86/* ------------------------------------------------------------------------- */
  87/* ACEX1K Passive Serial Generic Implementation                                  */
  88
  89static int ACEX1K_ps_load(Altera_desc *desc, const void *buf, size_t bsize)
  90{
  91        int ret_val = FPGA_FAIL;        /* assume the worst */
  92        Altera_ACEX1K_Passive_Serial_fns *fn = desc->iface_fns;
  93        int i;
  94
  95        PRINTF ("%s: start with interface functions @ 0x%p\n",
  96                        __FUNCTION__, fn);
  97
  98        if (fn) {
  99                size_t bytecount = 0;
 100                unsigned char *data = (unsigned char *) buf;
 101                int cookie = desc->cookie;      /* make a local copy */
 102                unsigned long ts;               /* timestamp */
 103
 104                PRINTF ("%s: Function Table:\n"
 105                                "ptr:\t0x%p\n"
 106                                "struct: 0x%p\n"
 107                                "config:\t0x%p\n"
 108                                "status:\t0x%p\n"
 109                                "clk:\t0x%p\n"
 110                                "data:\t0x%p\n"
 111                                "done:\t0x%p\n\n",
 112                                __FUNCTION__, &fn, fn, fn->config, fn->status,
 113                                fn->clk, fn->data, fn->done);
 114#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
 115                printf ("Loading FPGA Device %d...", cookie);
 116#endif
 117
 118                /*
 119                 * Run the pre configuration function if there is one.
 120                 */
 121                if (*fn->pre) {
 122                        (*fn->pre) (cookie);
 123                }
 124
 125                /* Establish the initial state */
 126                (*fn->config) (true, true, cookie);     /* Assert nCONFIG */
 127
 128                udelay(2);              /* T_cfg > 2us  */
 129
 130                /* nSTATUS should be asserted now */
 131                (*fn->done) (cookie);
 132                if ( !(*fn->status) (cookie) ) {
 133                        puts ("** nSTATUS is not asserted.\n");
 134                        (*fn->abort) (cookie);
 135                        return FPGA_FAIL;
 136                }
 137
 138                (*fn->config) (false, true, cookie);    /* Deassert nCONFIG */
 139                udelay(2);              /* T_cf2st1 < 4us       */
 140
 141                /* Wait for nSTATUS to be released (i.e. deasserted) */
 142                ts = get_timer (0);             /* get current time */
 143                do {
 144                        CONFIG_FPGA_DELAY ();
 145                        if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) {    /* check the time */
 146                                puts ("** Timeout waiting for STATUS to go high.\n");
 147                                (*fn->abort) (cookie);
 148                                return FPGA_FAIL;
 149                        }
 150                        (*fn->done) (cookie);
 151                } while ((*fn->status) (cookie));
 152
 153                /* Get ready for the burn */
 154                CONFIG_FPGA_DELAY ();
 155
 156                /* Load the data */
 157                while (bytecount < bsize) {
 158                        unsigned char val=0;
 159#ifdef CONFIG_SYS_FPGA_CHECK_CTRLC
 160                        if (ctrlc ()) {
 161                                (*fn->abort) (cookie);
 162                                return FPGA_FAIL;
 163                        }
 164#endif
 165                        /* Altera detects an error if INIT goes low (active)
 166                           while DONE is low (inactive) */
 167#if 0 /* not yet implemented */
 168                        if ((*fn->done) (cookie) == 0 && (*fn->init) (cookie)) {
 169                                puts ("** CRC error during FPGA load.\n");
 170                                (*fn->abort) (cookie);
 171                                return (FPGA_FAIL);
 172                        }
 173#endif
 174                        val = data [bytecount ++ ];
 175                        i = 8;
 176                        do {
 177                                /* Deassert the clock */
 178                                (*fn->clk) (false, true, cookie);
 179                                CONFIG_FPGA_DELAY ();
 180                                /* Write data */
 181                                (*fn->data) ((val & 0x01), true, cookie);
 182                                CONFIG_FPGA_DELAY ();
 183                                /* Assert the clock */
 184                                (*fn->clk) (true, true, cookie);
 185                                CONFIG_FPGA_DELAY ();
 186                                val >>= 1;
 187                                i --;
 188                        } while (i > 0);
 189
 190#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
 191                        if (bytecount % (bsize / 40) == 0)
 192                                putc ('.');             /* let them know we are alive */
 193#endif
 194                }
 195
 196                CONFIG_FPGA_DELAY ();
 197
 198#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
 199                putc (' ');                     /* terminate the dotted line */
 200#endif
 201
 202        /*
 203         * Checking FPGA's CONF_DONE signal - correctly booted ?
 204         */
 205
 206        if ( ! (*fn->done) (cookie) ) {
 207                puts ("** Booting failed! CONF_DONE is still deasserted.\n");
 208                (*fn->abort) (cookie);
 209                return (FPGA_FAIL);
 210        }
 211
 212        /*
 213         * "DCLK must be clocked an additional 10 times fpr ACEX 1K..."
 214         */
 215
 216        for (i = 0; i < 12; i++) {
 217                CONFIG_FPGA_DELAY ();
 218                (*fn->clk) (true, true, cookie);        /* Assert the clock pin */
 219                CONFIG_FPGA_DELAY ();
 220                (*fn->clk) (false, true, cookie);       /* Deassert the clock pin */
 221        }
 222
 223        ret_val = FPGA_SUCCESS;
 224
 225#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
 226                if (ret_val == FPGA_SUCCESS) {
 227                        puts ("Done.\n");
 228                }
 229                else {
 230                        puts ("Fail.\n");
 231                }
 232#endif
 233        (*fn->post) (cookie);
 234
 235        } else {
 236                printf ("%s: NULL Interface function table!\n", __FUNCTION__);
 237        }
 238
 239        return ret_val;
 240}
 241
 242static int ACEX1K_ps_dump(Altera_desc *desc, const void *buf, size_t bsize)
 243{
 244        /* Readback is only available through the Slave Parallel and         */
 245        /* boundary-scan interfaces.                                         */
 246        printf ("%s: Passive Serial Dumping is unavailable\n",
 247                        __FUNCTION__);
 248        return FPGA_FAIL;
 249}
 250