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