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