uboot/board/esd/pmc440/fpga.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2007
   3 * Matthias Fuchs, esd gmbh, matthias.fuchs@esd-electronics.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#include <common.h>
  25#include <asm/io.h>
  26#include <spartan2.h>
  27#include <spartan3.h>
  28#include <command.h>
  29#include "fpga.h"
  30#include "pmc440.h"
  31
  32DECLARE_GLOBAL_DATA_PTR;
  33
  34#if defined(CONFIG_FPGA)
  35
  36#define USE_SP_CODE
  37
  38#ifdef USE_SP_CODE
  39Xilinx_Spartan3_Slave_Parallel_fns pmc440_fpga_fns = {
  40        fpga_pre_config_fn,
  41        fpga_pgm_fn,
  42        fpga_init_fn,
  43        NULL, /* err */
  44        fpga_done_fn,
  45        fpga_clk_fn,
  46        fpga_cs_fn,
  47        fpga_wr_fn,
  48        NULL, /* rdata */
  49        fpga_wdata_fn,
  50        fpga_busy_fn,
  51        fpga_abort_fn,
  52        fpga_post_config_fn,
  53};
  54#else
  55Xilinx_Spartan3_Slave_Serial_fns pmc440_fpga_fns = {
  56        fpga_pre_config_fn,
  57        fpga_pgm_fn,
  58        fpga_clk_fn,
  59        fpga_init_fn,
  60        fpga_done_fn,
  61        fpga_wr_fn,
  62        fpga_post_config_fn,
  63};
  64#endif
  65
  66Xilinx_Spartan2_Slave_Serial_fns ngcc_fpga_fns = {
  67        ngcc_fpga_pre_config_fn,
  68        ngcc_fpga_pgm_fn,
  69        ngcc_fpga_clk_fn,
  70        ngcc_fpga_init_fn,
  71        ngcc_fpga_done_fn,
  72        ngcc_fpga_wr_fn,
  73        ngcc_fpga_post_config_fn
  74};
  75
  76Xilinx_desc fpga[CONFIG_FPGA_COUNT] = {
  77        XILINX_XC3S1200E_DESC(
  78#ifdef USE_SP_CODE
  79                slave_parallel,
  80#else
  81                slave_serial,
  82#endif
  83                (void *)&pmc440_fpga_fns,
  84                0),
  85        XILINX_XC2S200_DESC(
  86                slave_serial,
  87                (void *)&ngcc_fpga_fns,
  88                0)
  89};
  90
  91
  92/*
  93 * Set the active-low FPGA reset signal.
  94 */
  95void fpga_reset(int assert)
  96{
  97        debug("%s:%d: RESET ", __FUNCTION__, __LINE__);
  98        if (assert) {
  99                out_be32((void*)GPIO1_OR, in_be32((void*)GPIO1_OR) & ~GPIO1_FPGA_DATA);
 100                debug("asserted\n");
 101        } else {
 102                out_be32((void*)GPIO1_OR, in_be32((void*)GPIO1_OR) | GPIO1_FPGA_DATA);
 103                debug("deasserted\n");
 104        }
 105}
 106
 107
 108/*
 109 * Initialize the SelectMap interface.  We assume that the mode and the
 110 * initial state of all of the port pins have already been set!
 111 */
 112void fpga_serialslave_init(void)
 113{
 114        debug("%s:%d: Initialize serial slave interface\n", __FUNCTION__,
 115              __LINE__);
 116        fpga_pgm_fn(FALSE, FALSE, 0);   /* make sure program pin is inactive */
 117}
 118
 119
 120/*
 121 * Set the FPGA's active-low SelectMap program line to the specified level
 122 */
 123int fpga_pgm_fn(int assert, int flush, int cookie)
 124{
 125        debug("%s:%d: FPGA PROGRAM ",
 126              __FUNCTION__, __LINE__);
 127
 128        if (assert) {
 129                out_be32((void*)GPIO1_OR, in_be32((void*)GPIO1_OR) & ~GPIO1_FPGA_PRG);
 130                debug("asserted\n");
 131        } else {
 132                out_be32((void*)GPIO1_OR, in_be32((void*)GPIO1_OR) | GPIO1_FPGA_PRG);
 133                debug("deasserted\n");
 134        }
 135        return assert;
 136}
 137
 138
 139/*
 140 * Test the state of the active-low FPGA INIT line.  Return 1 on INIT
 141 * asserted (low).
 142 */
 143int fpga_init_fn(int cookie)
 144{
 145        if (in_be32((void*)GPIO1_IR) & GPIO1_FPGA_INIT)
 146                return 0;
 147        else
 148                return 1;
 149}
 150
 151#ifdef USE_SP_CODE
 152int fpga_abort_fn(int cookie)
 153{
 154        return 0;
 155}
 156
 157
 158int fpga_cs_fn(int assert_cs, int flush, int cookie)
 159{
 160        return assert_cs;
 161}
 162
 163
 164int fpga_busy_fn(int cookie)
 165{
 166        return 1;
 167}
 168#endif
 169
 170
 171/*
 172 * Test the state of the active-high FPGA DONE pin
 173 */
 174int fpga_done_fn(int cookie)
 175{
 176        if (in_be32((void*)GPIO1_IR) & GPIO1_FPGA_DONE)
 177                return 1;
 178        else
 179                return 0;
 180}
 181
 182
 183/*
 184 * FPGA pre-configuration function. Just make sure that
 185 * FPGA reset is asserted to keep the FPGA from starting up after
 186 * configuration.
 187 */
 188int fpga_pre_config_fn(int cookie)
 189{
 190        debug("%s:%d: FPGA pre-configuration\n", __FUNCTION__, __LINE__);
 191        fpga_reset(TRUE);
 192
 193        /* release init# */
 194        out_be32((void*)GPIO0_OR, in_be32((void*)GPIO0_OR) | GPIO0_FPGA_FORCEINIT);
 195        /* disable PLD IOs */
 196        out_be32((void*)GPIO1_OR, in_be32((void*)GPIO1_OR) | GPIO1_IOEN_N);
 197        return 0;
 198}
 199
 200
 201/*
 202 * FPGA post configuration function. Blip the FPGA reset line and then see if
 203 * the FPGA appears to be running.
 204 */
 205int fpga_post_config_fn(int cookie)
 206{
 207        pmc440_fpga_t *fpga = (pmc440_fpga_t *)FPGA_BA;
 208        int rc=0;
 209        char *s;
 210
 211        debug("%s:%d: FPGA post configuration\n", __FUNCTION__, __LINE__);
 212
 213        /* enable PLD0..7 pins */
 214        out_be32((void*)GPIO1_OR, in_be32((void*)GPIO1_OR) & ~GPIO1_IOEN_N);
 215
 216        fpga_reset(TRUE);
 217        udelay (100);
 218        fpga_reset(FALSE);
 219        udelay (100);
 220
 221        FPGA_OUT32(&fpga->status, (gd->board_type << STATUS_HWREV_SHIFT) & STATUS_HWREV_MASK);
 222
 223        /* NGCC/CANDES only: enable ledlink */
 224        if ((s = getenv("bd_type")) &&
 225            ((!strcmp(s, "ngcc")) || (!strcmp(s, "candes"))))
 226                FPGA_SETBITS(&fpga->ctrla, 0x29f8c000);
 227
 228        return rc;
 229}
 230
 231
 232int fpga_clk_fn(int assert_clk, int flush, int cookie)
 233{
 234        if (assert_clk)
 235                out_be32((void*)GPIO1_OR, in_be32((void*)GPIO1_OR) | GPIO1_FPGA_CLK);
 236        else
 237                out_be32((void*)GPIO1_OR, in_be32((void*)GPIO1_OR) & ~GPIO1_FPGA_CLK);
 238
 239        return assert_clk;
 240}
 241
 242
 243int fpga_wr_fn(int assert_write, int flush, int cookie)
 244{
 245        if (assert_write)
 246                out_be32((void*)GPIO1_OR, in_be32((void*)GPIO1_OR) | GPIO1_FPGA_DATA);
 247        else
 248                out_be32((void*)GPIO1_OR, in_be32((void*)GPIO1_OR) & ~GPIO1_FPGA_DATA);
 249
 250        return assert_write;
 251}
 252
 253#ifdef USE_SP_CODE
 254int fpga_wdata_fn(uchar data, int flush, int cookie)
 255{
 256        uchar val = data;
 257        ulong or = in_be32((void*)GPIO1_OR);
 258        int i = 7;
 259        do {
 260                /* Write data */
 261                if (val & 0x80)
 262                        or = (or & ~GPIO1_FPGA_CLK) | GPIO1_FPGA_DATA;
 263                else
 264                        or = or & ~(GPIO1_FPGA_CLK | GPIO1_FPGA_DATA);
 265
 266                out_be32((void*)GPIO1_OR, or);
 267
 268                /* Assert the clock */
 269                or |= GPIO1_FPGA_CLK;
 270                out_be32((void*)GPIO1_OR, or);
 271                val <<= 1;
 272                i --;
 273        } while (i > 0);
 274
 275        /* Write last data bit (the 8th clock comes from the sp_load() code */
 276        if (val & 0x80)
 277                or = (or & ~GPIO1_FPGA_CLK) | GPIO1_FPGA_DATA;
 278        else
 279                or = or & ~(GPIO1_FPGA_CLK | GPIO1_FPGA_DATA);
 280
 281        out_be32((void*)GPIO1_OR, or);
 282
 283        return 0;
 284}
 285#endif
 286
 287#define NGCC_FPGA_PRG  CLOCK_EN
 288#define NGCC_FPGA_DATA RESET_OUT
 289#define NGCC_FPGA_DONE CLOCK_IN
 290#define NGCC_FPGA_INIT IRIGB_R_IN
 291#define NGCC_FPGA_CLK  CLOCK_OUT
 292
 293void ngcc_fpga_serialslave_init(void)
 294{
 295        debug("%s:%d: Initialize serial slave interface\n",
 296              __FUNCTION__, __LINE__);
 297
 298        /* make sure program pin is inactive */
 299        ngcc_fpga_pgm_fn (FALSE, FALSE, 0);
 300}
 301
 302/*
 303 * Set the active-low FPGA reset signal.
 304 */
 305void ngcc_fpga_reset(int assert)
 306{
 307        debug("%s:%d: RESET ", __FUNCTION__, __LINE__);
 308
 309        if (assert) {
 310                FPGA_CLRBITS(NGCC_CTRL_BASE, NGCC_CTRL_FPGARST_N);
 311                debug("asserted\n");
 312        } else {
 313                FPGA_SETBITS(NGCC_CTRL_BASE, NGCC_CTRL_FPGARST_N);
 314                debug("deasserted\n");
 315        }
 316}
 317
 318
 319/*
 320 * Set the FPGA's active-low SelectMap program line to the specified level
 321 */
 322int ngcc_fpga_pgm_fn(int assert, int flush, int cookie)
 323{
 324        pmc440_fpga_t *fpga = (pmc440_fpga_t *)FPGA_BA;
 325
 326        debug("%s:%d: FPGA PROGRAM ", __FUNCTION__, __LINE__);
 327
 328        if (assert) {
 329                FPGA_CLRBITS(&fpga->ctrla, NGCC_FPGA_PRG);
 330                debug("asserted\n");
 331        } else {
 332                FPGA_SETBITS(&fpga->ctrla, NGCC_FPGA_PRG);
 333                debug("deasserted\n");
 334        }
 335
 336        return assert;
 337}
 338
 339
 340/*
 341 * Test the state of the active-low FPGA INIT line.  Return 1 on INIT
 342 * asserted (low).
 343 */
 344int ngcc_fpga_init_fn(int cookie)
 345{
 346        pmc440_fpga_t *fpga = (pmc440_fpga_t *)FPGA_BA;
 347
 348        debug("%s:%d: INIT check... ", __FUNCTION__, __LINE__);
 349        if (FPGA_IN32(&fpga->status) & NGCC_FPGA_INIT) {
 350                debug("high\n");
 351                return 0;
 352        } else {
 353                debug("low\n");
 354                return 1;
 355        }
 356}
 357
 358
 359/*
 360 * Test the state of the active-high FPGA DONE pin
 361 */
 362int ngcc_fpga_done_fn(int cookie)
 363{
 364        pmc440_fpga_t *fpga = (pmc440_fpga_t *)FPGA_BA;
 365
 366        debug("%s:%d: DONE check... ", __FUNCTION__, __LINE__);
 367        if (FPGA_IN32(&fpga->status) & NGCC_FPGA_DONE) {
 368                debug("DONE high\n");
 369                return 1;
 370        } else {
 371                debug("low\n");
 372                return 0;
 373        }
 374}
 375
 376
 377/*
 378 * FPGA pre-configuration function.
 379 */
 380int ngcc_fpga_pre_config_fn(int cookie)
 381{
 382        pmc440_fpga_t *fpga = (pmc440_fpga_t *)FPGA_BA;
 383        debug("%s:%d: FPGA pre-configuration\n", __FUNCTION__, __LINE__);
 384
 385        ngcc_fpga_reset(TRUE);
 386        FPGA_CLRBITS(&fpga->ctrla, 0xfffffe00);
 387
 388        ngcc_fpga_reset(TRUE);
 389        return 0;
 390}
 391
 392
 393/*
 394 * FPGA post configuration function. Blip the FPGA reset line and then see if
 395 * the FPGA appears to be running.
 396 */
 397int ngcc_fpga_post_config_fn(int cookie)
 398{
 399        pmc440_fpga_t *fpga = (pmc440_fpga_t *)FPGA_BA;
 400
 401        debug("%s:%d: NGCC FPGA post configuration\n", __FUNCTION__, __LINE__);
 402
 403        udelay (100);
 404        ngcc_fpga_reset(FALSE);
 405
 406        FPGA_SETBITS(&fpga->ctrla, 0x29f8c000);
 407
 408        return 0;
 409}
 410
 411
 412int ngcc_fpga_clk_fn(int assert_clk, int flush, int cookie)
 413{
 414        pmc440_fpga_t *fpga = (pmc440_fpga_t *)FPGA_BA;
 415
 416        if (assert_clk)
 417                FPGA_SETBITS(&fpga->ctrla, NGCC_FPGA_CLK);
 418        else
 419                FPGA_CLRBITS(&fpga->ctrla, NGCC_FPGA_CLK);
 420
 421        return assert_clk;
 422}
 423
 424
 425int ngcc_fpga_wr_fn(int assert_write, int flush, int cookie)
 426{
 427        pmc440_fpga_t *fpga = (pmc440_fpga_t *)FPGA_BA;
 428
 429        if (assert_write)
 430                FPGA_SETBITS(&fpga->ctrla, NGCC_FPGA_DATA);
 431        else
 432                FPGA_CLRBITS(&fpga->ctrla, NGCC_FPGA_DATA);
 433
 434        return assert_write;
 435}
 436
 437
 438/*
 439 * Initialize the fpga.  Return 1 on success, 0 on failure.
 440 */
 441int pmc440_init_fpga(void)
 442{
 443        char *s;
 444
 445        debug("%s:%d: Initialize FPGA interface\n",
 446              __FUNCTION__, __LINE__);
 447        fpga_init();
 448
 449        fpga_serialslave_init ();
 450        debug("%s:%d: Adding fpga 0\n", __FUNCTION__, __LINE__);
 451        fpga_add (fpga_xilinx, &fpga[0]);
 452
 453        /* NGCC only */
 454        if ((s = getenv("bd_type")) && !strcmp(s, "ngcc")) {
 455                ngcc_fpga_serialslave_init ();
 456                debug("%s:%d: Adding fpga 1\n", __FUNCTION__, __LINE__);
 457                fpga_add (fpga_xilinx, &fpga[1]);
 458        }
 459
 460        return 0;
 461}
 462#endif /* CONFIG_FPGA */
 463