uboot/board/astro/mcf5373l/fpga.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * (C) Copyright 2006
   4 * Wolfgang Wegner, ASTRO Strobel Kommunikationssysteme GmbH,
   5 * w.wegner@astro-kom.de
   6 *
   7 * based on the files by
   8 * Heiko Schocher, DENX Software Engineering, hs@denx.de
   9 * and
  10 * Rich Ireland, Enterasys Networks, rireland@enterasys.com.
  11 * Keith Outwater, keith_outwater@mvis.com.
  12 */
  13
  14/* Altera/Xilinx FPGA configuration support for the ASTRO "URMEL" board */
  15
  16#include <common.h>
  17#include <console.h>
  18#include <watchdog.h>
  19#include <altera.h>
  20#include <ACEX1K.h>
  21#include <spartan3.h>
  22#include <command.h>
  23#include <asm/immap_5329.h>
  24#include <asm/io.h>
  25#include "fpga.h"
  26
  27int altera_pre_fn(int cookie)
  28{
  29        gpio_t *gpiop = (gpio_t *)MMAP_GPIO;
  30        unsigned char tmp_char;
  31        unsigned short tmp_short;
  32
  33        /* first, set the required pins to GPIO function */
  34        /* PAR_T0IN -> GPIO */
  35        tmp_char = readb(&gpiop->par_timer);
  36        tmp_char &= 0xfc;
  37        writeb(tmp_char, &gpiop->par_timer);
  38        /* all QSPI pins -> GPIO */
  39        writew(0x0000, &gpiop->par_qspi);
  40        /* U0RTS, U0CTS -> GPIO */
  41        tmp_short = __raw_readw(&gpiop->par_uart);
  42        tmp_short &= 0xfff3;
  43        __raw_writew(tmp_short, &gpiop->par_uart);
  44        /* all PWM pins -> GPIO */
  45        writeb(0x00, &gpiop->par_pwm);
  46        /* next, set data direction registers */
  47        writeb(0x01, &gpiop->pddr_timer);
  48        writeb(0x25, &gpiop->pddr_qspi);
  49        writeb(0x0c, &gpiop->pddr_uart);
  50        writeb(0x04, &gpiop->pddr_pwm);
  51
  52        /* ensure other SPI peripherals are deselected */
  53        writeb(0x08, &gpiop->ppd_uart);
  54        writeb(0x38, &gpiop->ppd_qspi);
  55
  56        /* CONFIG = 0 STATUS = 0 -> FPGA in reset state */
  57        writeb(0xFB, &gpiop->pclrr_uart);
  58        /* enable Altera configuration by clearing QSPI_CS2 and DT0IN */
  59        writeb(0xFE, &gpiop->pclrr_timer);
  60        writeb(0xDF, &gpiop->pclrr_qspi);
  61        return FPGA_SUCCESS;
  62}
  63
  64/* Set the state of CONFIG Pin */
  65int altera_config_fn(int assert_config, int flush, int cookie)
  66{
  67        gpio_t *gpiop = (gpio_t *)MMAP_GPIO;
  68
  69        if (assert_config)
  70                writeb(0x04, &gpiop->ppd_uart);
  71        else
  72                writeb(0xFB, &gpiop->pclrr_uart);
  73        return FPGA_SUCCESS;
  74}
  75
  76/* Returns the state of STATUS Pin */
  77int altera_status_fn(int cookie)
  78{
  79        gpio_t *gpiop = (gpio_t *)MMAP_GPIO;
  80
  81        if (readb(&gpiop->ppd_pwm) & 0x08)
  82                return FPGA_FAIL;
  83        return FPGA_SUCCESS;
  84}
  85
  86/* Returns the state of CONF_DONE Pin */
  87int altera_done_fn(int cookie)
  88{
  89        gpio_t *gpiop = (gpio_t *)MMAP_GPIO;
  90
  91        if (readb(&gpiop->ppd_pwm) & 0x20)
  92                return FPGA_FAIL;
  93        return FPGA_SUCCESS;
  94}
  95
  96/*
  97 * writes the complete buffer to the FPGA
  98 * writing the complete buffer in one function is much faster,
  99 * then calling it for every bit
 100 */
 101int altera_write_fn(const void *buf, size_t len, int flush, int cookie)
 102{
 103        size_t bytecount = 0;
 104        gpio_t *gpiop = (gpio_t *)MMAP_GPIO;
 105        unsigned char *data = (unsigned char *)buf;
 106        unsigned char val = 0;
 107        int i;
 108        int len_40 = len / 40;
 109
 110        while (bytecount < len) {
 111                val = data[bytecount++];
 112                i = 8;
 113                do {
 114                        writeb(0xFB, &gpiop->pclrr_qspi);
 115                        if (val & 0x01)
 116                                writeb(0x01, &gpiop->ppd_qspi);
 117                        else
 118                                writeb(0xFE, &gpiop->pclrr_qspi);
 119                        writeb(0x04, &gpiop->ppd_qspi);
 120                        val >>= 1;
 121                        i--;
 122                } while (i > 0);
 123
 124                if (bytecount % len_40 == 0) {
 125#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
 126                        WATCHDOG_RESET();
 127#endif
 128#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
 129                        putc('.');      /* let them know we are alive */
 130#endif
 131#ifdef CONFIG_SYS_FPGA_CHECK_CTRLC
 132                        if (ctrlc())
 133                                return FPGA_FAIL;
 134#endif
 135                }
 136        }
 137        return FPGA_SUCCESS;
 138}
 139
 140/* called, when programming is aborted */
 141int altera_abort_fn(int cookie)
 142{
 143        gpio_t *gpiop = (gpio_t *)MMAP_GPIO;
 144
 145        writeb(0x20, &gpiop->ppd_qspi);
 146        writeb(0x08, &gpiop->ppd_uart);
 147        return FPGA_SUCCESS;
 148}
 149
 150/* called, when programming was succesful */
 151int altera_post_fn(int cookie)
 152{
 153        return altera_abort_fn(cookie);
 154}
 155
 156/*
 157 * Note that these are pointers to code that is in Flash. They will be
 158 * relocated at runtime.
 159 * FIXME: relocation not yet working for coldfire, see below!
 160 */
 161Altera_CYC2_Passive_Serial_fns altera_fns = {
 162        altera_pre_fn,
 163        altera_config_fn,
 164        altera_status_fn,
 165        altera_done_fn,
 166        altera_write_fn,
 167        altera_abort_fn,
 168        altera_post_fn
 169};
 170
 171Altera_desc altera_fpga[CONFIG_FPGA_COUNT] = {
 172        {Altera_CYC2,
 173         passive_serial,
 174         85903,
 175         (void *)&altera_fns,
 176         NULL,
 177         0}
 178};
 179
 180/* Initialize the fpga.  Return 1 on success, 0 on failure. */
 181int astro5373l_altera_load(void)
 182{
 183        int i;
 184
 185        for (i = 0; i < CONFIG_FPGA_COUNT; i++) {
 186                /*
 187                 * I did not yet manage to get relocation work properly,
 188                 * so set stuff here instead of static initialisation:
 189                 */
 190                altera_fns.pre = altera_pre_fn;
 191                altera_fns.config = altera_config_fn;
 192                altera_fns.status = altera_status_fn;
 193                altera_fns.done = altera_done_fn;
 194                altera_fns.write = altera_write_fn;
 195                altera_fns.abort = altera_abort_fn;
 196                altera_fns.post = altera_post_fn;
 197                altera_fpga[i].iface_fns = (void *)&altera_fns;
 198                fpga_add(fpga_altera, &altera_fpga[i]);
 199        }
 200        return 1;
 201}
 202
 203/* Set the FPGA's PROG_B line to the specified level */
 204int xilinx_pgm_config_fn(int assert, int flush, int cookie)
 205{
 206        gpio_t *gpiop = (gpio_t *)MMAP_GPIO;
 207
 208        if (assert)
 209                writeb(0xFB, &gpiop->pclrr_uart);
 210        else
 211                writeb(0x04, &gpiop->ppd_uart);
 212        return assert;
 213}
 214
 215/*
 216 * Test the state of the active-low FPGA INIT line.  Return 1 on INIT
 217 * asserted (low).
 218 */
 219int xilinx_init_config_fn(int cookie)
 220{
 221        gpio_t *gpiop = (gpio_t *)MMAP_GPIO;
 222
 223        return (readb(&gpiop->ppd_pwm) & 0x08) == 0;
 224}
 225
 226/* Test the state of the active-high FPGA DONE pin */
 227int xilinx_done_config_fn(int cookie)
 228{
 229        gpio_t *gpiop = (gpio_t *)MMAP_GPIO;
 230
 231        return (readb(&gpiop->ppd_pwm) & 0x20) >> 5;
 232}
 233
 234/* Abort an FPGA operation */
 235int xilinx_abort_config_fn(int cookie)
 236{
 237        gpio_t *gpiop = (gpio_t *)MMAP_GPIO;
 238        /* ensure all SPI peripherals and FPGAs are deselected */
 239        writeb(0x08, &gpiop->ppd_uart);
 240        writeb(0x01, &gpiop->ppd_timer);
 241        writeb(0x38, &gpiop->ppd_qspi);
 242        return FPGA_FAIL;
 243}
 244
 245/*
 246 * FPGA pre-configuration function. Just make sure that
 247 * FPGA reset is asserted to keep the FPGA from starting up after
 248 * configuration.
 249 */
 250int xilinx_pre_config_fn(int cookie)
 251{
 252        gpio_t *gpiop = (gpio_t *)MMAP_GPIO;
 253        unsigned char tmp_char;
 254        unsigned short tmp_short;
 255
 256        /* first, set the required pins to GPIO function */
 257        /* PAR_T0IN -> GPIO */
 258        tmp_char = readb(&gpiop->par_timer);
 259        tmp_char &= 0xfc;
 260        writeb(tmp_char, &gpiop->par_timer);
 261        /* all QSPI pins -> GPIO */
 262        writew(0x0000, &gpiop->par_qspi);
 263        /* U0RTS, U0CTS -> GPIO */
 264        tmp_short = __raw_readw(&gpiop->par_uart);
 265        tmp_short &= 0xfff3;
 266        __raw_writew(tmp_short, &gpiop->par_uart);
 267        /* all PWM pins -> GPIO */
 268        writeb(0x00, &gpiop->par_pwm);
 269        /* next, set data direction registers */
 270        writeb(0x01, &gpiop->pddr_timer);
 271        writeb(0x25, &gpiop->pddr_qspi);
 272        writeb(0x0c, &gpiop->pddr_uart);
 273        writeb(0x04, &gpiop->pddr_pwm);
 274
 275        /* ensure other SPI peripherals are deselected */
 276        writeb(0x08, &gpiop->ppd_uart);
 277        writeb(0x38, &gpiop->ppd_qspi);
 278        writeb(0x01, &gpiop->ppd_timer);
 279
 280        /* CONFIG = 0, STATUS = 0 -> FPGA in reset state */
 281        writeb(0xFB, &gpiop->pclrr_uart);
 282        /* enable Xilinx configuration by clearing QSPI_CS2 and U0CTS */
 283        writeb(0xF7, &gpiop->pclrr_uart);
 284        writeb(0xDF, &gpiop->pclrr_qspi);
 285        return 0;
 286}
 287
 288/*
 289 * FPGA post configuration function. Should perform a test if FPGA is running.
 290 */
 291int xilinx_post_config_fn(int cookie)
 292{
 293        int rc = 0;
 294
 295        /*
 296         * no test yet
 297         */
 298        return rc;
 299}
 300
 301int xilinx_clk_config_fn(int assert_clk, int flush, int cookie)
 302{
 303        gpio_t *gpiop = (gpio_t *)MMAP_GPIO;
 304
 305        if (assert_clk)
 306                writeb(0x04, &gpiop->ppd_qspi);
 307        else
 308                writeb(0xFB, &gpiop->pclrr_qspi);
 309        return assert_clk;
 310}
 311
 312int xilinx_wr_config_fn(int assert_write, int flush, int cookie)
 313{
 314        gpio_t *gpiop = (gpio_t *)MMAP_GPIO;
 315
 316        if (assert_write)
 317                writeb(0x01, &gpiop->ppd_qspi);
 318        else
 319                writeb(0xFE, &gpiop->pclrr_qspi);
 320        return assert_write;
 321}
 322
 323int xilinx_fastwr_config_fn(void *buf, size_t len, int flush, int cookie)
 324{
 325        size_t bytecount = 0;
 326        gpio_t *gpiop = (gpio_t *)MMAP_GPIO;
 327        unsigned char *data = (unsigned char *)buf;
 328        unsigned char val = 0;
 329        int i;
 330        int len_40 = len / 40;
 331
 332        for (bytecount = 0; bytecount < len; bytecount++) {
 333                val = *(data++);
 334                for (i = 8; i > 0; i--) {
 335                        writeb(0xFB, &gpiop->pclrr_qspi);
 336                        if (val & 0x80)
 337                                writeb(0x01, &gpiop->ppd_qspi);
 338                        else
 339                                writeb(0xFE, &gpiop->pclrr_qspi);
 340                        writeb(0x04, &gpiop->ppd_qspi);
 341                        val <<= 1;
 342                }
 343                if (bytecount % len_40 == 0) {
 344#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
 345                        WATCHDOG_RESET();
 346#endif
 347#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
 348                        putc('.');      /* let them know we are alive */
 349#endif
 350#ifdef CONFIG_SYS_FPGA_CHECK_CTRLC
 351                        if (ctrlc())
 352                                return FPGA_FAIL;
 353#endif
 354                }
 355        }
 356        return FPGA_SUCCESS;
 357}
 358
 359/*
 360 * Note that these are pointers to code that is in Flash.  They will be
 361 * relocated at runtime.
 362 * FIXME: relocation not yet working for coldfire, see below!
 363 */
 364xilinx_spartan3_slave_serial_fns xilinx_fns = {
 365        xilinx_pre_config_fn,
 366        xilinx_pgm_config_fn,
 367        xilinx_clk_config_fn,
 368        xilinx_init_config_fn,
 369        xilinx_done_config_fn,
 370        xilinx_wr_config_fn,
 371        0,
 372        xilinx_fastwr_config_fn
 373};
 374
 375xilinx_desc xilinx_fpga[CONFIG_FPGA_COUNT] = {
 376        {xilinx_spartan3,
 377         slave_serial,
 378         XILINX_XC3S4000_SIZE,
 379         (void *)&xilinx_fns,
 380         0,
 381         &spartan3_op}
 382};
 383
 384/* Initialize the fpga.  Return 1 on success, 0 on failure. */
 385int astro5373l_xilinx_load(void)
 386{
 387        int i;
 388
 389        fpga_init();
 390
 391        for (i = 0; i < CONFIG_FPGA_COUNT; i++) {
 392                /*
 393                 * I did not yet manage to get relocation work properly,
 394                 * so set stuff here instead of static initialisation:
 395                 */
 396                xilinx_fns.pre = xilinx_pre_config_fn;
 397                xilinx_fns.pgm = xilinx_pgm_config_fn;
 398                xilinx_fns.clk = xilinx_clk_config_fn;
 399                xilinx_fns.init = xilinx_init_config_fn;
 400                xilinx_fns.done = xilinx_done_config_fn;
 401                xilinx_fns.wr = xilinx_wr_config_fn;
 402                xilinx_fns.bwr = xilinx_fastwr_config_fn;
 403                xilinx_fpga[i].iface_fns = (void *)&xilinx_fns;
 404                fpga_add(fpga_xilinx, &xilinx_fpga[i]);
 405        }
 406        return 1;
 407}
 408