uboot/board/siemens/common/fpga.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2002
   3 * Wolfgang Grandegger, DENX Software Engineering, wg@denx.de.
   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>
  26#include <command.h>
  27#include <linux/ctype.h>
  28#include <common.h>
  29
  30#include "fpga.h"
  31
  32int  power_on_reset(void);
  33
  34/* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  35
  36
  37static int fpga_get_version(fpga_t* fpga, char* name)
  38{
  39    char vname[12];
  40    /*
  41     * Net-list string format:
  42     *     "vvvvvvvvddddddddn...".
  43     *     Version Date    Name
  44     *     "0000000322042002PUMA" = PUMA version 3 from 22.04.2002.
  45     */
  46    if (strlen(name) < (16 + strlen(fpga->name)))
  47        goto failure;
  48    /* Check FPGA name */
  49    if (strcmp(&name[16], fpga->name) != 0)
  50        goto failure;
  51    /* Get version number */
  52    memcpy(vname, name, 8);
  53    vname[8] = '\0';
  54    return simple_strtoul(vname, NULL, 16);
  55
  56 failure:
  57    printf("Image name %s is invalid\n", name);
  58    return -1;
  59}
  60
  61/* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  62
  63static fpga_t* fpga_get(char* fpga_name)
  64{
  65    char name[FPGA_NAME_LEN];
  66    int i;
  67
  68    if (strlen(fpga_name) >= FPGA_NAME_LEN)
  69        goto failure;
  70    for (i = 0; i < strlen(fpga_name); i++)
  71        name[i] = toupper(fpga_name[i]);
  72    name[i] = '\0';
  73    for (i = 0; i < fpga_count; i++) {
  74        if (strcmp(name, fpga_list[i].name) == 0)
  75            return &fpga_list[i];
  76    }
  77 failure:
  78    printf("FPGA: name %s is invalid\n", fpga_name);
  79    return NULL;
  80}
  81
  82/* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  83
  84static void fpga_status (fpga_t* fpga)
  85{
  86    /* Check state */
  87    if (fpga_control(fpga, FPGA_DONE_IS_HIGH))
  88        printf ("%s is loaded (%08lx)\n",
  89                fpga->name, fpga_control(fpga, FPGA_GET_ID));
  90    else
  91        printf ("%s is NOT loaded\n", fpga->name);
  92}
  93
  94/* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  95
  96#define FPGA_RESET_TIMEOUT 100 /* = 10 ms */
  97
  98static int fpga_reset (fpga_t* fpga)
  99{
 100    int i;
 101
 102    /* Set PROG to low and wait til INIT goes low */
 103    fpga_control(fpga, FPGA_PROG_SET_LOW);
 104    for (i = 0; i < FPGA_RESET_TIMEOUT; i++) {
 105        udelay (100);
 106        if (!fpga_control(fpga, FPGA_INIT_IS_HIGH))
 107            break;
 108    }
 109    if (i == FPGA_RESET_TIMEOUT)
 110        goto failure;
 111
 112    /* Set PROG to high and wait til INIT goes high */
 113    fpga_control(fpga, FPGA_PROG_SET_HIGH);
 114    for (i = 0; i < FPGA_RESET_TIMEOUT; i++) {
 115        udelay (100);
 116        if (fpga_control(fpga, FPGA_INIT_IS_HIGH))
 117            break;
 118    }
 119    if (i == FPGA_RESET_TIMEOUT)
 120        goto failure;
 121
 122    return 0;
 123 failure:
 124    return 1;
 125}
 126
 127/* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
 128
 129#define FPGA_LOAD_TIMEOUT 100 /* = 10 ms */
 130
 131static int fpga_load (fpga_t* fpga, ulong addr, int checkall)
 132{
 133    volatile uchar *fpga_addr = (volatile uchar *)fpga->conf_base;
 134    image_header_t *hdr = (image_header_t *)addr;
 135    ulong len;
 136    uchar *data;
 137    char msg[32];
 138    int verify, i;
 139
 140#if defined(CONFIG_FIT)
 141    if (genimg_get_format ((void *)hdr) != IMAGE_FORMAT_LEGACY) {
 142        puts ("Non legacy image format not supported\n");
 143        return -1;
 144    }
 145#endif
 146
 147    /*
 148     * Check the image header and data of the net-list
 149     */
 150    if (!image_check_magic (hdr)) {
 151        strcpy (msg, "Bad Image Magic Number");
 152        goto failure;
 153    }
 154
 155    if (!image_check_hcrc (hdr)) {
 156        strcpy (msg, "Bad Image Header CRC");
 157        goto failure;
 158    }
 159
 160    data = (uchar*)image_get_data (hdr);
 161    len  = image_get_data_size (hdr);
 162
 163    verify = getenv_yesno ("verify");
 164    if (verify) {
 165        if (!image_check_dcrc (hdr)) {
 166            strcpy (msg, "Bad Image Data CRC");
 167            goto failure;
 168        }
 169    }
 170
 171    if (checkall && fpga_get_version(fpga, image_get_name (hdr)) < 0)
 172        return 1;
 173
 174    /* align length */
 175    if (len & 1)
 176        ++len;
 177
 178    /*
 179     * Reset FPGA and wait for completion
 180     */
 181    if (fpga_reset(fpga)) {
 182        strcpy (msg, "Reset Timeout");
 183        goto failure;
 184    }
 185
 186    printf ("(%s)... ", image_get_name (hdr));
 187    /*
 188     * Copy data to FPGA
 189     */
 190    fpga_control (fpga, FPGA_LOAD_MODE);
 191    while (len--) {
 192        *fpga_addr = *data++;
 193    }
 194    fpga_control (fpga, FPGA_READ_MODE);
 195
 196    /*
 197     * Wait for completion and check error status if timeout
 198     */
 199    for (i = 0; i < FPGA_LOAD_TIMEOUT; i++) {
 200        udelay (100);
 201        if (fpga_control (fpga, FPGA_DONE_IS_HIGH))
 202            break;
 203    }
 204    if (i == FPGA_LOAD_TIMEOUT) {
 205        if (fpga_control(fpga, FPGA_INIT_IS_HIGH))
 206            strcpy(msg, "Invalid Size");
 207        else
 208            strcpy(msg, "CRC Error");
 209        goto failure;
 210    }
 211
 212    printf("done\n");
 213    return 0;
 214
 215 failure:
 216
 217    printf("ERROR: %s\n", msg);
 218    return 1;
 219}
 220
 221#if defined(CONFIG_CMD_BSP)
 222
 223/* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
 224
 225int do_fpga (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
 226{
 227    ulong addr = 0;
 228    int i;
 229    fpga_t* fpga;
 230
 231    if (argc < 2)
 232        goto failure;
 233
 234    if (strncmp(argv[1], "stat", 4) == 0) {             /* status */
 235        if (argc == 2) {
 236            for (i = 0; i < fpga_count; i++) {
 237                fpga_status (&fpga_list[i]);
 238            }
 239        }
 240        else if (argc == 3) {
 241            if ((fpga = fpga_get(argv[2])) == 0)
 242                goto failure;
 243            fpga_status (fpga);
 244        }
 245        else
 246            goto failure;
 247    }
 248    else if (strcmp(argv[1],"load") == 0) {             /* load */
 249        if (argc == 3 && fpga_count == 1) {
 250            fpga = &fpga_list[0];
 251        }
 252        else if (argc == 4) {
 253            if ((fpga = fpga_get(argv[2])) == 0)
 254                goto failure;
 255        }
 256        else
 257            goto failure;
 258
 259        addr = simple_strtoul(argv[argc-1], NULL, 16);
 260
 261        printf ("FPGA load %s: addr %08lx: ",
 262                fpga->name, addr);
 263        fpga_load (fpga, addr, 1);
 264
 265    }
 266    else if (strncmp(argv[1], "rese", 4) == 0) {        /* reset */
 267        if (argc == 2 && fpga_count == 1) {
 268            fpga = &fpga_list[0];
 269        }
 270        else if (argc == 3) {
 271            if ((fpga = fpga_get(argv[2])) == 0)
 272                goto failure;
 273        }
 274        else
 275            goto failure;
 276
 277        printf ("FPGA reset %s: ", fpga->name);
 278        if (fpga_reset(fpga))
 279            printf ("ERROR: Timeout\n");
 280        else
 281            printf ("done\n");
 282    }
 283    else
 284        goto failure;
 285
 286    return 0;
 287
 288 failure:
 289    cmd_usage(cmdtp);
 290    return 1;
 291}
 292
 293U_BOOT_CMD(
 294        fpga,   4,      1,      do_fpga,
 295        "access FPGA(s)",
 296        "fpga status [name] - print FPGA status\n"
 297        "fpga reset  [name] - reset FPGA\n"
 298        "fpga load [name] addr - load FPGA configuration data\n"
 299);
 300
 301#endif
 302
 303/* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
 304
 305int fpga_init (void)
 306{
 307    ulong addr;
 308    ulong new_id, old_id = 0;
 309    image_header_t *hdr;
 310    fpga_t* fpga;
 311    int do_load, i, j;
 312    char name[16], *s;
 313
 314    /*
 315     *  Port setup for FPGA control
 316     */
 317    for (i = 0; i < fpga_count; i++) {
 318        fpga_control(&fpga_list[i], FPGA_INIT_PORTS);
 319    }
 320
 321    /*
 322     * Load FPGA(s): a new net-list is loaded if the FPGA is
 323     * empty, Power-on-Reset or the old one is not up-to-date
 324     */
 325    for (i = 0; i < fpga_count; i++) {
 326        fpga = &fpga_list[i];
 327        printf ("%s:  ", fpga->name);
 328
 329        for (j = 0; j < strlen(fpga->name); j++)
 330            name[j] = tolower(fpga->name[j]);
 331        name[j] = '\0';
 332        sprintf(name, "%s_addr", name);
 333        addr = 0;
 334        if ((s = getenv(name)) != NULL)
 335            addr = simple_strtoul(s, NULL, 16);
 336
 337        if (!addr) {
 338            printf ("env. variable %s undefined\n", name);
 339            return 1;
 340        }
 341
 342        hdr = (image_header_t *)addr;
 343#if defined(CONFIG_FIT)
 344        if (genimg_get_format ((void *)hdr) != IMAGE_FORMAT_LEGACY) {
 345           puts ("Non legacy image format not supported\n");
 346           return -1;
 347        }
 348#endif
 349
 350        if ((new_id = fpga_get_version(fpga, image_get_name (hdr))) == -1)
 351            return 1;
 352
 353        do_load = 1;
 354
 355        if (!power_on_reset() && fpga_control(fpga, FPGA_DONE_IS_HIGH)) {
 356            old_id = fpga_control(fpga, FPGA_GET_ID);
 357            if (new_id == old_id)
 358                do_load = 0;
 359        }
 360
 361        if (do_load) {
 362            printf ("loading ");
 363            fpga_load (fpga, addr, 0);
 364        } else {
 365            printf ("loaded (%08lx)\n", old_id);
 366        }
 367    }
 368
 369    return 0;
 370}
 371