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