uboot/post/board/lwmon5/fpga.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2008 Dmitry Rakhchev, EmCraft Systems, rda@emcraft.com
   3 *
   4 * Developed for DENX Software Engineering GmbH
   5 *
   6 * See file CREDITS for list of people who contributed to this
   7 * project.
   8 *
   9 * This program is free software; you can redistribute it and/or
  10 * modify it under the terms of the GNU General Public License as
  11 * published by the Free Software Foundation; either version 2 of
  12 * the License, or (at your option) any later version.
  13 *
  14 * This program is distributed in the hope that it will be useful,
  15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17 * GNU General Public License for more details.
  18 *
  19 * You should have received a copy of the GNU General Public License
  20 * along with this program; if not, write to the Free Software
  21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  22 * MA 02111-1307 USA
  23 */
  24#include <common.h>
  25
  26/* This test performs testing of FPGA SCRATCH register,
  27 * gets FPGA version and run get_ram_size() on FPGA memory
  28 */
  29
  30#include <post.h>
  31#include <watchdog.h>
  32#include <asm/io.h>
  33
  34DECLARE_GLOBAL_DATA_PTR;
  35
  36#define FPGA_SCRATCH_REG        0xC4000050
  37#define FPGA_VERSION_REG        0xC4000040
  38#define FPGA_RAM_START          0xC4200000
  39#define FPGA_RAM_END            0xC4203FFF
  40#define FPGA_STAT               0xC400000C
  41#define FPGA_BUFFER             0x00800000
  42#define FPGA_RAM_SIZE           (FPGA_RAM_END - FPGA_RAM_START + 1)
  43
  44#if CONFIG_POST & CONFIG_SYS_POST_BSPEC3
  45
  46const static unsigned long pattern[] = {
  47        0xffffffff,
  48        0xaaaaaaaa,
  49        0xcccccccc,
  50        0xf0f0f0f0,
  51        0xff00ff00,
  52        0xffff0000,
  53        0x0000ffff,
  54        0x00ff00ff,
  55        0x0f0f0f0f,
  56        0x33333333,
  57        0x55555555,
  58        0x00000000,
  59};
  60
  61const static unsigned long otherpattern = 0x01234567;
  62
  63static int one_scratch_test(uint value)
  64{
  65        uint read_value;
  66        int ret = 0;
  67
  68        out_be32((void *)FPGA_SCRATCH_REG, value);
  69        /* read other location (protect against data lines capacity) */
  70        ret = in_be16((void *)FPGA_VERSION_REG);
  71        /* verify test pattern */
  72        read_value = in_be32((void *)FPGA_SCRATCH_REG);
  73        if (read_value != value) {
  74                post_log("FPGA SCRATCH test failed write %08X, read %08X\n",
  75                         value, read_value);
  76                ret = -1;
  77        }
  78
  79        return ret;
  80}
  81
  82static int fpga_post_test1(ulong *start, ulong size, ulong val)
  83{
  84        int ret = 0;
  85        ulong i = 0;
  86        ulong *mem = start;
  87        ulong readback;
  88
  89        for (i = 0; i < size / sizeof(ulong); i++) {
  90                mem[i] = val;
  91                if (i % 1024 == 0)
  92                        WATCHDOG_RESET();
  93        }
  94
  95        for (i = 0; i < size / sizeof(ulong); i++) {
  96                readback = mem[i];
  97                if (readback != val) {
  98                        post_log("FPGA Memory error at %08x, "
  99                                 "wrote %08x, read %08x !\n",
 100                                 mem + i, val, readback);
 101                        ret = -1;
 102                        break;
 103                }
 104                if (i % 1024 == 0)
 105                        WATCHDOG_RESET();
 106        }
 107        return ret;
 108}
 109
 110static int fpga_post_test2(ulong *start, ulong size)
 111{
 112        int ret = 0;
 113        ulong i = 0;
 114        ulong *mem = start;
 115        ulong readback;
 116
 117        for (i = 0; i < size / sizeof(ulong); i++) {
 118                mem[i] = 1 << (i % 32);
 119                if (i % 1024 == 0)
 120                        WATCHDOG_RESET();
 121        }
 122
 123        for (i = 0; i < size / sizeof(ulong); i++) {
 124                readback = mem[i];
 125                if (readback != 1 << (i % 32)) {
 126                        post_log("FPGA Memory error at %08x, "
 127                                 "wrote %08x, read %08x !\n",
 128                                 mem + i, 1 << (i % 32), readback);
 129                        ret = -1;
 130                        break;
 131                }
 132                if (i % 1024 == 0)
 133                        WATCHDOG_RESET();
 134        }
 135
 136        return ret;
 137}
 138
 139static int fpga_post_test3(ulong *start, ulong size)
 140{
 141        int ret = 0;
 142        ulong i = 0;
 143        ulong *mem = start;
 144        ulong readback;
 145
 146        for (i = 0; i < size / sizeof(ulong); i++) {
 147                mem[i] = i;
 148                if (i % 1024 == 0)
 149                        WATCHDOG_RESET();
 150        }
 151
 152        for (i = 0; i < size / sizeof(ulong); i++) {
 153                readback = mem[i];
 154                if (readback != i) {
 155                        post_log("FPGA Memory error at %08x, "
 156                                 "wrote %08x, read %08x !\n",
 157                                 mem + i, i, readback);
 158                        ret = -1;
 159                        break;
 160                }
 161                if (i % 1024 == 0)
 162                        WATCHDOG_RESET();
 163        }
 164
 165        return ret;
 166}
 167
 168static int fpga_post_test4(ulong *start, ulong size)
 169{
 170        int ret = 0;
 171        ulong i = 0;
 172        ulong *mem = start;
 173        ulong readback;
 174
 175        for (i = 0; i < size / sizeof(ulong); i++) {
 176                mem[i] = ~i;
 177                if (i % 1024 == 0)
 178                        WATCHDOG_RESET();
 179        }
 180
 181        for (i = 0; i < size / sizeof(ulong); i++) {
 182                readback = mem[i];
 183                if (readback != ~i) {
 184                        post_log("FPGA Memory error at %08x, "
 185                                 "wrote %08x, read %08x !\n",
 186                                 mem + i, ~i, readback);
 187                        ret = -1;
 188                        break;
 189                }
 190                if (i % 1024 == 0)
 191                        WATCHDOG_RESET();
 192        }
 193
 194        return ret;
 195}
 196
 197/* FPGA Memory-pattern-test */
 198static int fpga_mem_test(void)
 199{
 200        int ret = 0;
 201        ulong* start = (ulong *)FPGA_RAM_START;
 202        ulong  size  = FPGA_RAM_SIZE;
 203
 204        if (ret == 0)
 205                ret = fpga_post_test1(start, size, 0x00000000);
 206
 207        if (ret == 0)
 208                ret = fpga_post_test1(start, size, 0xffffffff);
 209
 210        if (ret == 0)
 211                ret = fpga_post_test1(start, size, 0x55555555);
 212
 213        if (ret == 0)
 214                ret = fpga_post_test1(start, size, 0xaaaaaaaa);
 215
 216        WATCHDOG_RESET();
 217
 218        if (ret == 0)
 219                ret = fpga_post_test2(start, size);
 220
 221        if (ret == 0)
 222                ret = fpga_post_test3(start, size);
 223
 224        if (ret == 0)
 225                ret = fpga_post_test4(start, size);
 226
 227        return ret;
 228}
 229
 230/* Verify FPGA addresslines */
 231static int fpga_post_addrline(ulong *address, ulong *base, ulong size)
 232{
 233        unsigned long *target;
 234        unsigned long *end;
 235        unsigned long readback;
 236        unsigned long xor;
 237        int ret = 0;
 238
 239        end = (ulong *)((ulong)base + size);
 240        xor = 0;
 241
 242        for (xor = sizeof(ulong); xor > 0; xor <<= 1) {
 243                target = (ulong*)((ulong)address ^ xor);
 244                if ((target >= base) && (target < end)) {
 245                        *address = ~*target;
 246                        readback = *target;
 247
 248                        if (readback == *address) {
 249                                post_log("Memory (address line) error at %08x"
 250                                         "XOR value %08x !\n",
 251                                         address, target, xor);
 252                                ret = -1;
 253                                break;
 254                        }
 255                }
 256        }
 257
 258        return ret;
 259}
 260
 261/* Verify FPGA addresslines */
 262static int fpga_post_dataline(ulong *address)
 263{
 264        unsigned long temp32 = 0;
 265        int i = 0;
 266        int ret = 0;
 267
 268        for (i = 0; i < ARRAY_SIZE(pattern); i++) {
 269                *address = pattern[i];
 270                /*
 271                 * Put a different pattern on the data lines: otherwise they
 272                 * may float long enough to read back what we wrote.
 273                 */
 274                *(address + 1) = otherpattern;
 275                temp32 = *address;
 276
 277                if (temp32 != pattern[i]){
 278                        post_log("Memory (date line) error at %08x, "
 279                                 "wrote %08x, read %08x !\n",
 280                                 address, pattern[i], temp32);
 281                        ret = 1;
 282                }
 283        }
 284
 285        return ret;
 286}
 287
 288/* Verify FPGA, get version & memory size */
 289int fpga_post_test(int flags)
 290{
 291        uint   old_value;
 292        uint   version;
 293        uint   read_value;
 294        int    ret = 0;
 295
 296        post_log("\n");
 297        old_value = in_be32((void *)FPGA_SCRATCH_REG);
 298
 299        if (one_scratch_test(0x55555555))
 300                ret = 1;
 301        if (one_scratch_test(0xAAAAAAAA))
 302                ret = 1;
 303
 304        out_be32((void *)FPGA_SCRATCH_REG, old_value);
 305
 306        version = in_be32((void *)FPGA_VERSION_REG);
 307        post_log("FPGA version %u.%u\n",
 308                 (version >> 8) & 0xFF, version & 0xFF);
 309
 310        /* Enable write to FPGA RAM */
 311        out_be32((void *)FPGA_STAT, in_be32((void *)FPGA_STAT) | 0x1000);
 312
 313        /* get RAM size */
 314        read_value = get_ram_size((void *)CONFIG_SYS_FPGA_BASE_1, FPGA_RAM_SIZE);
 315        post_log("FPGA RAM size %d bytes\n", read_value);
 316        WATCHDOG_RESET();
 317
 318        /* copy fpga memory to DDR2 RAM*/
 319        memcpy((void *)FPGA_BUFFER,(void *)FPGA_RAM_START, FPGA_RAM_SIZE);
 320        WATCHDOG_RESET();
 321
 322        /* Test datalines */
 323        if (fpga_post_dataline((ulong *)FPGA_RAM_START)) {
 324                ret = 1;
 325                goto out;
 326        }
 327        WATCHDOG_RESET();
 328
 329        /* Test addresslines */
 330        if (fpga_post_addrline((ulong *)FPGA_RAM_START,
 331                               (ulong *)FPGA_RAM_START, FPGA_RAM_SIZE)) {
 332                ret = 1;
 333                goto out;
 334        }
 335        WATCHDOG_RESET();
 336        if (fpga_post_addrline((ulong *)FPGA_RAM_END - sizeof(long),
 337                               (ulong *)FPGA_RAM_START, FPGA_RAM_SIZE)) {
 338                ret = 1;
 339                goto out;
 340        }
 341        WATCHDOG_RESET();
 342
 343        /* Memory Pattern Test */
 344        if (fpga_mem_test()) {
 345                ret = 1;
 346                goto out;
 347        }
 348        WATCHDOG_RESET();
 349
 350        /* restore memory */
 351        memcpy((void *)FPGA_RAM_START,(void *)FPGA_BUFFER, FPGA_RAM_SIZE);
 352        WATCHDOG_RESET();
 353
 354out:
 355        /* Disable write to RAM */
 356        out_be32((void *)FPGA_STAT, in_be32((void *)FPGA_STAT) & 0xEFFF);
 357        return ret;
 358}
 359
 360#endif /* CONFIG_POST & CONFIG_SYS_POST_BSPEC3 */
 361