uboot/board/esd/pmc440/cmd_pmc440.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2007-2008
   3 * Matthias Fuchs, esd Gmbh, matthias.fuchs@esd-electronics.com.
   4 *
   5 * SPDX-License-Identifier:     GPL-2.0+
   6 */
   7#include <common.h>
   8#include <command.h>
   9#include <asm/io.h>
  10#include <asm/cache.h>
  11#include <asm/processor.h>
  12#if defined(CONFIG_LOGBUFFER)
  13#include <logbuff.h>
  14#endif
  15
  16#include "pmc440.h"
  17
  18int is_monarch(void);
  19int bootstrap_eeprom_write(unsigned dev_addr, unsigned offset,
  20                           uchar *buffer, unsigned cnt);
  21int eeprom_write_enable(unsigned dev_addr, int state);
  22
  23DECLARE_GLOBAL_DATA_PTR;
  24
  25#if defined(CONFIG_CMD_BSP)
  26
  27static int got_fifoirq;
  28static int got_hcirq;
  29
  30int fpga_interrupt(u32 arg)
  31{
  32        pmc440_fpga_t *fpga = (pmc440_fpga_t *)arg;
  33        int rc = -1; /* not for us */
  34        u32 status = FPGA_IN32(&fpga->status);
  35
  36        /* check for interrupt from fifo module */
  37        if (status & STATUS_FIFO_ISF) {
  38                /* disable this int source */
  39                FPGA_OUT32(&fpga->hostctrl, HOSTCTRL_FIFOIE_GATE);
  40                rc = 0;
  41                got_fifoirq = 1; /* trigger backend */
  42        }
  43
  44        if (status & STATUS_HOST_ISF) {
  45                FPGA_OUT32(&fpga->hostctrl, HOSTCTRL_HCINT_GATE);
  46                rc = 0;
  47                got_hcirq = 1;
  48        }
  49
  50        return rc;
  51}
  52
  53int do_waithci(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
  54{
  55        pmc440_fpga_t *fpga = (pmc440_fpga_t *)FPGA_BA;
  56
  57        got_hcirq = 0;
  58
  59        FPGA_CLRBITS(&fpga->ctrla, CTRL_HOST_IE);
  60        FPGA_OUT32(&fpga->hostctrl, HOSTCTRL_HCINT_GATE);
  61
  62        irq_install_handler(IRQ0_FPGA,
  63                            (interrupt_handler_t *)fpga_interrupt,
  64                            fpga);
  65
  66        FPGA_SETBITS(&fpga->ctrla, CTRL_HOST_IE);
  67
  68        while (!got_hcirq) {
  69                /* Abort if ctrl-c was pressed */
  70                if (ctrlc()) {
  71                        puts("\nAbort\n");
  72                        break;
  73                }
  74        }
  75        if (got_hcirq)
  76                printf("Got interrupt!\n");
  77
  78        FPGA_CLRBITS(&fpga->ctrla, CTRL_HOST_IE);
  79        irq_free_handler(IRQ0_FPGA);
  80        return 0;
  81}
  82U_BOOT_CMD(
  83        waithci,        1,      1,      do_waithci,
  84        "Wait for host control interrupt",
  85        ""
  86);
  87
  88void dump_fifo(pmc440_fpga_t *fpga, int f, int *n)
  89{
  90        u32 ctrl;
  91
  92        while (!((ctrl = FPGA_IN32(&fpga->fifo[f].ctrl)) & FIFO_EMPTY)) {
  93                printf("%5d  %d    %3d  %08x",
  94                       (*n)++, f, ctrl & (FIFO_LEVEL_MASK | FIFO_FULL),
  95                       FPGA_IN32(&fpga->fifo[f].data));
  96                if (ctrl & FIFO_OVERFLOW) {
  97                        printf(" OVERFLOW\n");
  98                        FPGA_CLRBITS(&fpga->fifo[f].ctrl, FIFO_OVERFLOW);
  99                } else
 100                        printf("\n");
 101        }
 102}
 103
 104int do_fifo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 105{
 106        pmc440_fpga_t *fpga = (pmc440_fpga_t *)FPGA_BA;
 107        int i;
 108        int n = 0;
 109        u32 ctrl, data, f;
 110        char str[] = "\\|/-";
 111        int abort = 0;
 112        int count = 0;
 113        int count2 = 0;
 114
 115        switch (argc) {
 116        case 1:
 117                /* print all fifos status information */
 118                printf("fifo level status\n");
 119                printf("______________________________\n");
 120                for (i=0; i<FIFO_COUNT; i++) {
 121                        ctrl = FPGA_IN32(&fpga->fifo[i].ctrl);
 122                        printf(" %d    %3d  %s%s%s %s\n",
 123                               i, ctrl & (FIFO_LEVEL_MASK | FIFO_FULL),
 124                               ctrl & FIFO_FULL ? "FULL     " : "",
 125                               ctrl & FIFO_EMPTY ? "EMPTY    " : "",
 126                               ctrl & (FIFO_FULL|FIFO_EMPTY) ? "" : "NOT EMPTY",
 127                               ctrl & FIFO_OVERFLOW ? "OVERFLOW" : "");
 128                }
 129                break;
 130
 131        case 2:
 132                /* completely read out fifo 'n' */
 133                if (!strcmp(argv[1],"read")) {
 134                        printf("  #   fifo level data\n");
 135                        printf("______________________________\n");
 136
 137                        for (i=0; i<FIFO_COUNT; i++)
 138                                dump_fifo(fpga, i, &n);
 139
 140                } else if (!strcmp(argv[1],"wait")) {
 141                        got_fifoirq = 0;
 142
 143                        irq_install_handler(IRQ0_FPGA,
 144                                            (interrupt_handler_t *)fpga_interrupt,
 145                                            fpga);
 146
 147                        printf("  #   fifo level data\n");
 148                        printf("______________________________\n");
 149
 150                        /* enable all fifo interrupts */
 151                        FPGA_OUT32(&fpga->hostctrl,
 152                                   HOSTCTRL_FIFOIE_GATE | HOSTCTRL_FIFOIE_FLAG);
 153                        for (i=0; i<FIFO_COUNT; i++) {
 154                                /* enable interrupts from all fifos */
 155                                FPGA_SETBITS(&fpga->fifo[i].ctrl, FIFO_IE);
 156                        }
 157
 158                        while (1) {
 159                                /* wait loop */
 160                                while (!got_fifoirq) {
 161                                        count++;
 162                                        if (!(count % 100)) {
 163                                                count2++;
 164                                                putc(0x08); /* backspace */
 165                                                putc(str[count2 % 4]);
 166                                        }
 167
 168                                        /* Abort if ctrl-c was pressed */
 169                                        if ((abort = ctrlc())) {
 170                                                puts("\nAbort\n");
 171                                                break;
 172                                        }
 173                                        udelay(1000);
 174                                }
 175                                if (abort)
 176                                        break;
 177
 178                                /* simple fifo backend */
 179                                if (got_fifoirq) {
 180                                        for (i=0; i<FIFO_COUNT; i++)
 181                                                dump_fifo(fpga, i, &n);
 182
 183                                        got_fifoirq = 0;
 184                                        /* unmask global fifo irq */
 185                                        FPGA_OUT32(&fpga->hostctrl,
 186                                                   HOSTCTRL_FIFOIE_GATE |
 187                                                   HOSTCTRL_FIFOIE_FLAG);
 188                                }
 189                        }
 190
 191                        /* disable all fifo interrupts */
 192                        FPGA_OUT32(&fpga->hostctrl, HOSTCTRL_FIFOIE_GATE);
 193                        for (i=0; i<FIFO_COUNT; i++)
 194                                FPGA_CLRBITS(&fpga->fifo[i].ctrl, FIFO_IE);
 195
 196                        irq_free_handler(IRQ0_FPGA);
 197
 198                } else {
 199                        printf("Usage:\nfifo %s\n", cmdtp->help);
 200                        return 1;
 201                }
 202                break;
 203
 204        case 4:
 205        case 5:
 206                if (!strcmp(argv[1],"write")) {
 207                        /* get fifo number or fifo address */
 208                        f = simple_strtoul(argv[2], NULL, 16);
 209
 210                        /* data paramter */
 211                        data = simple_strtoul(argv[3], NULL, 16);
 212
 213                        /* get optional count parameter */
 214                        n = 1;
 215                        if (argc >= 5)
 216                                n = (int)simple_strtoul(argv[4], NULL, 10);
 217
 218                        if (f < FIFO_COUNT) {
 219                                printf("writing %d x %08x to fifo %d\n",
 220                                       n, data, f);
 221                                for (i=0; i<n; i++)
 222                                        FPGA_OUT32(&fpga->fifo[f].data, data);
 223                        } else {
 224                                printf("writing %d x %08x to fifo port at "
 225                                       "address %08x\n",
 226                                       n, data, f);
 227                                for (i=0; i<n; i++)
 228                                        out_be32((void *)f, data);
 229                        }
 230                } else {
 231                        printf("Usage:\nfifo %s\n", cmdtp->help);
 232                        return 1;
 233                }
 234                break;
 235
 236        default:
 237                printf("Usage:\nfifo %s\n", cmdtp->help);
 238                return 1;
 239        }
 240        return 0;
 241}
 242U_BOOT_CMD(
 243        fifo,   5,      1,      do_fifo,
 244        "Fifo module operations",
 245        "wait\nfifo read\n"
 246        "fifo write fifo(0..3) data [cnt=1]\n"
 247        "fifo write address(>=4) data [cnt=1]\n"
 248        "  - without arguments: print all fifo's status\n"
 249        "  - with 'wait' argument: interrupt driven read from all fifos\n"
 250        "  - with 'read' argument: read current contents from all fifos\n"
 251        "  - with 'write' argument: write 'data' 'cnt' times to "
 252        "'fifo' or 'address'"
 253);
 254
 255int do_setup_bootstrap_eeprom(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 256{
 257        ulong sdsdp[5];
 258        ulong delay;
 259        int count=16;
 260
 261        if (argc < 2) {
 262                printf("Usage:\nsbe %s\n", cmdtp->help);
 263                return -1;
 264        }
 265
 266        if (argc > 1) {
 267                if (!strcmp(argv[1], "400")) {
 268                        /* PLB=133MHz, PLB/PCI=3 */
 269                        printf("Bootstrapping for 400MHz\n");
 270                        sdsdp[0]=0x8678624e;
 271                        sdsdp[1]=0x095fa030;
 272                        sdsdp[2]=0x40082350;
 273                        sdsdp[3]=0x0d050000;
 274                } else if (!strcmp(argv[1], "533")) {
 275                        /* PLB=133MHz, PLB/PCI=3 */
 276                        printf("Bootstrapping for 533MHz\n");
 277                        sdsdp[0]=0x87788252;
 278                        sdsdp[1]=0x095fa030;
 279                        sdsdp[2]=0x40082350;
 280                        sdsdp[3]=0x0d050000;
 281                } else if (!strcmp(argv[1], "667")) {
 282                        /* PLB=133MHz, PLB/PCI=3 */
 283                        printf("Bootstrapping for 667MHz\n");
 284                        sdsdp[0]=0x8778a256;
 285                        sdsdp[1]=0x095fa030;
 286                        sdsdp[2]=0x40082350;
 287                        sdsdp[3]=0x0d050000;
 288                } else {
 289                        printf("Usage:\nsbe %s\n", cmdtp->help);
 290                        return -1;
 291                }
 292        }
 293
 294        if (argc > 2) {
 295                sdsdp[4] = 0;
 296                if (argv[2][0]=='1')
 297                        sdsdp[4]=0x19750100;
 298                else if (argv[2][0]=='0')
 299                        sdsdp[4]=0x19750000;
 300                if (sdsdp[4])
 301                        count += 4;
 302        }
 303
 304        if (argc > 3) {
 305                delay = simple_strtoul(argv[3], NULL, 10);
 306                if (delay > 20)
 307                        delay = 20;
 308                sdsdp[4] |= delay;
 309        }
 310
 311        printf("Writing boot EEPROM ...\n");
 312        if (bootstrap_eeprom_write(CONFIG_SYS_I2C_BOOT_EEPROM_ADDR,
 313                                   0, (uchar*)sdsdp, count) != 0)
 314                printf("bootstrap_eeprom_write failed\n");
 315        else
 316                printf("done (dump via 'i2c md 52 0.1 14')\n");
 317
 318        return 0;
 319}
 320U_BOOT_CMD(
 321        sbe, 4, 0, do_setup_bootstrap_eeprom,
 322        "setup bootstrap eeprom",
 323        "<cpufreq:400|533|667> [<console-uart:0|1> [<bringup delay (0..20s)>]]"
 324);
 325
 326#if defined(CONFIG_PRAM)
 327#include <environment.h>
 328#include <search.h>
 329#include <errno.h>
 330
 331int do_painit(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 332{
 333        u32 pram, nextbase, base;
 334        char *v;
 335        u32 param;
 336        ulong *lptr;
 337
 338        env_t *envp;
 339        char *res;
 340        int len;
 341
 342        v = getenv("pram");
 343        if (v)
 344                pram = simple_strtoul(v, NULL, 10);
 345        else {
 346                printf("Error: pram undefined. Please define pram in KiB\n");
 347                return 1;
 348        }
 349
 350        base = gd->bd->bi_memsize;
 351#if defined(CONFIG_LOGBUFFER)
 352        base -= LOGBUFF_LEN + LOGBUFF_OVERHEAD;
 353#endif
 354        /*
 355         * gd->bd->bi_memsize == physical ram size - CONFIG_SYS_MEM_TOP_HIDE
 356         */
 357        param = base - (pram << 10);
 358        printf("PARAM: @%08x\n", param);
 359        debug("memsize=0x%08x, base=0x%08x\n", (u32)gd->bd->bi_memsize, base);
 360
 361        /* clear entire PA ram */
 362        memset((void*)param, 0, (pram << 10));
 363
 364        /* reserve 4k for pointer field */
 365        nextbase = base - 4096;
 366        lptr = (ulong*)(base);
 367
 368        /*
 369         * *(--lptr) = item_size;
 370         * *(--lptr) = base - item_base = distance from field top;
 371         */
 372
 373        /* env is first (4k aligned) */
 374        nextbase -= ((CONFIG_ENV_SIZE + 4096 - 1) & ~(4096 - 1));
 375        envp = (env_t *)nextbase;
 376        res = (char *)envp->data;
 377        len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
 378        if (len < 0) {
 379                error("Cannot export environment: errno = %d\n", errno);
 380                return 1;
 381        }
 382        envp->crc = crc32(0, envp->data, ENV_SIZE);
 383
 384        *(--lptr) = CONFIG_ENV_SIZE;     /* size */
 385        *(--lptr) = base - nextbase;  /* offset | type=0 */
 386
 387        /* free section */
 388        *(--lptr) = nextbase - param; /* size */
 389        *(--lptr) = (base - param) | 126; /* offset | type=126 */
 390
 391        /* terminate pointer field */
 392        *(--lptr) = crc32(0, (void*)(base - 0x10), 0x10);
 393        *(--lptr) = 0;                /* offset=0 -> terminator */
 394        return 0;
 395}
 396U_BOOT_CMD(
 397        painit, 1,      1,      do_painit,
 398        "prepare PciAccess system",
 399        ""
 400);
 401#endif /* CONFIG_PRAM */
 402
 403int do_selfreset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 404{
 405        in_be32((void*)CONFIG_SYS_RESET_BASE);
 406        return 0;
 407}
 408U_BOOT_CMD(
 409        selfreset,      1,      1,      do_selfreset,
 410        "assert self-reset# signal",
 411        ""
 412);
 413
 414int do_resetout(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 415{
 416        pmc440_fpga_t *fpga = (pmc440_fpga_t *)FPGA_BA;
 417
 418        /* requiers bootet FPGA and PLD_IOEN_N active */
 419        if (in_be32((void*)GPIO1_OR) & GPIO1_IOEN_N) {
 420                printf("Error: resetout requires a bootet FPGA\n");
 421                return -1;
 422        }
 423
 424        if (argc > 1) {
 425                if (argv[1][0] == '0') {
 426                        /* assert */
 427                        printf("PMC-RESETOUT# asserted\n");
 428                        FPGA_OUT32(&fpga->hostctrl,
 429                                   HOSTCTRL_PMCRSTOUT_GATE);
 430                } else {
 431                        /* deassert */
 432                        printf("PMC-RESETOUT# deasserted\n");
 433                        FPGA_OUT32(&fpga->hostctrl,
 434                                   HOSTCTRL_PMCRSTOUT_GATE |
 435                                   HOSTCTRL_PMCRSTOUT_FLAG);
 436                }
 437        } else {
 438                printf("PMC-RESETOUT# is %s\n",
 439                       FPGA_IN32(&fpga->hostctrl) & HOSTCTRL_PMCRSTOUT_FLAG ?
 440                       "inactive" : "active");
 441        }
 442
 443        return 0;
 444}
 445U_BOOT_CMD(
 446        resetout,       2,      1,      do_resetout,
 447        "assert PMC-RESETOUT# signal",
 448        ""
 449);
 450
 451int do_inta(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 452{
 453        if (is_monarch()) {
 454                printf("This command is only supported in non-monarch mode\n");
 455                return -1;
 456        }
 457
 458        if (argc > 1) {
 459                if (argv[1][0] == '0') {
 460                        /* assert */
 461                        printf("inta# asserted\n");
 462                        out_be32((void*)GPIO1_TCR,
 463                                 in_be32((void*)GPIO1_TCR) | GPIO1_INTA_FAKE);
 464                } else {
 465                        /* deassert */
 466                        printf("inta# deasserted\n");
 467                        out_be32((void*)GPIO1_TCR,
 468                                 in_be32((void*)GPIO1_TCR) & ~GPIO1_INTA_FAKE);
 469                }
 470        } else {
 471                printf("inta# is %s\n",
 472                       in_be32((void*)GPIO1_TCR) & GPIO1_INTA_FAKE ?
 473                       "active" : "inactive");
 474        }
 475        return 0;
 476}
 477U_BOOT_CMD(
 478        inta,   2,      1,      do_inta,
 479        "Assert/Deassert or query INTA# state in non-monarch mode",
 480        ""
 481);
 482
 483/* test-only */
 484int do_pmm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 485{
 486        ulong pciaddr;
 487
 488        if (argc > 1) {
 489                pciaddr = simple_strtoul(argv[1], NULL, 16);
 490
 491                pciaddr &= 0xf0000000;
 492
 493                /* map PCI address at 0xc0000000 in PLB space */
 494
 495                /* PMM1 Mask/Attribute - disabled b4 setting */
 496                out32r(PCIL0_PMM1MA, 0x00000000);
 497                /* PMM1 Local Address */
 498                out32r(PCIL0_PMM1LA, 0xc0000000);
 499                /* PMM1 PCI Low Address */
 500                out32r(PCIL0_PMM1PCILA, pciaddr);
 501                /* PMM1 PCI High Address */
 502                out32r(PCIL0_PMM1PCIHA, 0x00000000);
 503                /* 256MB + No prefetching, and enable region */
 504                out32r(PCIL0_PMM1MA, 0xf0000001);
 505        } else {
 506                printf("Usage:\npmm %s\n", cmdtp->help);
 507        }
 508        return 0;
 509}
 510U_BOOT_CMD(
 511        pmm,    2,      1,      do_pmm,
 512        "Setup pmm[1] registers",
 513        "<pciaddr> (pciaddr will be aligned to 256MB)"
 514);
 515
 516#if defined(CONFIG_SYS_EEPROM_WREN)
 517int do_eep_wren(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 518{
 519        int query = argc == 1;
 520        int state = 0;
 521
 522        if (query) {
 523                /* Query write access state. */
 524                state = eeprom_write_enable(CONFIG_SYS_I2C_EEPROM_ADDR, -1);
 525                if (state < 0) {
 526                        puts("Query of write access state failed.\n");
 527                } else {
 528                        printf("Write access for device 0x%0x is %sabled.\n",
 529                               CONFIG_SYS_I2C_EEPROM_ADDR, state ? "en" : "dis");
 530                        state = 0;
 531                }
 532        } else {
 533                if ('0' == argv[1][0]) {
 534                        /* Disable write access. */
 535                        state = eeprom_write_enable(CONFIG_SYS_I2C_EEPROM_ADDR, 0);
 536                } else {
 537                        /* Enable write access. */
 538                        state = eeprom_write_enable(CONFIG_SYS_I2C_EEPROM_ADDR, 1);
 539                }
 540                if (state < 0) {
 541                        puts("Setup of write access state failed.\n");
 542                }
 543        }
 544
 545        return state;
 546}
 547U_BOOT_CMD(eepwren, 2, 0, do_eep_wren,
 548        "Enable / disable / query EEPROM write access",
 549        ""
 550);
 551#endif /* #if defined(CONFIG_SYS_EEPROM_WREN) */
 552
 553#endif /* CONFIG_CMD_BSP */
 554