/* * (C) Copyright 2007 * Matthias Fuchs, esd Gmbh, matthias.fuchs@esd-electronics.com. * * See file CREDITS for list of people who contributed to this * project. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA * */ #include #include #include #include #include #include "pmc440.h" int is_monarch(void); int bootstrap_eeprom_write(unsigned dev_addr, unsigned offset, uchar *buffer, unsigned cnt); int eeprom_write_enable(unsigned dev_addr, int state); DECLARE_GLOBAL_DATA_PTR; #if defined(CONFIG_CMD_BSP) static int got_fifoirq; static int got_hcirq; int fpga_interrupt(u32 arg) { pmc440_fpga_t *fpga = (pmc440_fpga_t *)arg; int rc = -1; /* not for us */ u32 status = FPGA_IN32(&fpga->status); /* check for interrupt from fifo module */ if (status & STATUS_FIFO_ISF) { /* disable this int source */ FPGA_OUT32(&fpga->hostctrl, HOSTCTRL_FIFOIE_GATE); rc = 0; got_fifoirq = 1; /* trigger backend */ } if (status & STATUS_HOST_ISF) { FPGA_OUT32(&fpga->hostctrl, HOSTCTRL_HCINT_GATE); rc = 0; got_hcirq = 1; } return rc; } int do_waithci(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) { pmc440_fpga_t *fpga = (pmc440_fpga_t *)FPGA_BA; got_hcirq = 0; FPGA_CLRBITS(&fpga->ctrla, CTRL_HOST_IE); FPGA_OUT32(&fpga->hostctrl, HOSTCTRL_HCINT_GATE); irq_install_handler(IRQ0_FPGA, (interrupt_handler_t *)fpga_interrupt, fpga); FPGA_SETBITS(&fpga->ctrla, CTRL_HOST_IE); while (!got_hcirq) { /* Abort if ctrl-c was pressed */ if (ctrlc()) { puts("\nAbort\n"); break; } } if (got_hcirq) printf("Got interrupt!\n"); FPGA_CLRBITS(&fpga->ctrla, CTRL_HOST_IE); irq_free_handler(IRQ0_FPGA); return 0; } U_BOOT_CMD( waithci, 1, 1, do_waithci, "waithci - Wait for host control interrupt\n", NULL ); void dump_fifo(pmc440_fpga_t *fpga, int f, int *n) { u32 ctrl; while (!((ctrl = FPGA_IN32(&fpga->fifo[f].ctrl)) & FIFO_EMPTY)) { printf("%5d %d %3d %08x", (*n)++, f, ctrl & (FIFO_LEVEL_MASK | FIFO_FULL), FPGA_IN32(&fpga->fifo[f].data)); if (ctrl & FIFO_OVERFLOW) { printf(" OVERFLOW\n"); FPGA_CLRBITS(&fpga->fifo[f].ctrl, FIFO_OVERFLOW); } else printf("\n"); } } int do_fifo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) { pmc440_fpga_t *fpga = (pmc440_fpga_t *)FPGA_BA; int i; int n = 0; u32 ctrl, data, f; char str[] = "\\|/-"; int abort = 0; int count = 0; int count2 = 0; switch (argc) { case 1: /* print all fifos status information */ printf("fifo level status\n"); printf("______________________________\n"); for (i=0; ififo[i].ctrl); printf(" %d %3d %s%s%s %s\n", i, ctrl & (FIFO_LEVEL_MASK | FIFO_FULL), ctrl & FIFO_FULL ? "FULL " : "", ctrl & FIFO_EMPTY ? "EMPTY " : "", ctrl & (FIFO_FULL|FIFO_EMPTY) ? "" : "NOT EMPTY", ctrl & FIFO_OVERFLOW ? "OVERFLOW" : ""); } break; case 2: /* completely read out fifo 'n' */ if (!strcmp(argv[1],"read")) { printf(" # fifo level data\n"); printf("______________________________\n"); for (i=0; ihostctrl, HOSTCTRL_FIFOIE_GATE | HOSTCTRL_FIFOIE_FLAG); for (i=0; ififo[i].ctrl, FIFO_IE); } while (1) { /* wait loop */ while (!got_fifoirq) { count++; if (!(count % 100)) { count2++; putc(0x08); /* backspace */ putc(str[count2 % 4]); } /* Abort if ctrl-c was pressed */ if ((abort = ctrlc())) { puts("\nAbort\n"); break; } udelay(1000); } if (abort) break; /* simple fifo backend */ if (got_fifoirq) { for (i=0; ihostctrl, HOSTCTRL_FIFOIE_GATE | HOSTCTRL_FIFOIE_FLAG); } } /* disable all fifo interrupts */ FPGA_OUT32(&fpga->hostctrl, HOSTCTRL_FIFOIE_GATE); for (i=0; ififo[i].ctrl, FIFO_IE); irq_free_handler(IRQ0_FPGA); } else { printf("Usage:\nfifo %s\n", cmdtp->help); return 1; } break; case 4: case 5: if (!strcmp(argv[1],"write")) { /* get fifo number or fifo address */ f = simple_strtoul(argv[2], NULL, 16); /* data paramter */ data = simple_strtoul(argv[3], NULL, 16); /* get optional count parameter */ n = 1; if (argc >= 5) n = (int)simple_strtoul(argv[4], NULL, 10); if (f < FIFO_COUNT) { printf("writing %d x %08x to fifo %d\n", n, data, f); for (i=0; ififo[f].data, data); } else { printf("writing %d x %08x to fifo port at address %08x\n", n, data, f); for (i=0; ihelp); return 1; } break; default: printf("Usage:\nfifo %s\n", cmdtp->help); return 1; } return 0; } U_BOOT_CMD( fifo, 5, 1, do_fifo, "fifo - Fifo module operations\n", "wait\nfifo read\n" "fifo write fifo(0..3) data [cnt=1]\n" "fifo write address(>=4) data [cnt=1]\n" " - without arguments: print all fifo's status\n" " - with 'wait' argument: interrupt driven read from all fifos\n" " - with 'read' argument: read current contents from all fifos\n" " - with 'write' argument: write 'data' 'cnt' times to 'fifo' or 'address'\n" ); int do_setup_bootstrap_eeprom(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) { ulong sdsdp[5]; ulong delay; int count=16; if (argc < 2) { printf("Usage:\nsbe %s\n", cmdtp->help); return -1; } if (argc > 1) { if (!strcmp(argv[1], "400")) { /* PLB=133MHz, PLB/PCI=4 */ printf("Bootstrapping for 400MHz\n"); sdsdp[0]=0x8678624e; sdsdp[1]=0x0947a030; sdsdp[2]=0x40082350; sdsdp[3]=0x0d050000; } else if (!strcmp(argv[1], "533")) { /* PLB=133MHz, PLB/PCI=3 */ printf("Bootstrapping for 533MHz\n"); sdsdp[0]=0x87788252; sdsdp[1]=0x095fa030; sdsdp[2]=0x40082350; sdsdp[3]=0x0d050000; } else if (!strcmp(argv[1], "667")) { /* PLB=133MHz, PLB/PCI=4 */ printf("Bootstrapping for 667MHz\n"); sdsdp[0]=0x8778a256; sdsdp[1]=0x0947a030; sdsdp[2]=0x40082350; sdsdp[3]=0x0d050000; } else if (!strcmp(argv[1], "test")) { /* TODO: this will replace the 667 MHz config above. * But it needs some more testing on a real 667 MHz CPU. */ printf("Bootstrapping for test (667MHz PLB=133PLB PLB/PCI=3)\n"); sdsdp[0]=0x8778a256; sdsdp[1]=0x095fa030; sdsdp[2]=0x40082350; sdsdp[3]=0x0d050000; } else { printf("Usage:\nsbe %s\n", cmdtp->help); return -1; } } if (argc > 2) { sdsdp[4] = 0; if (argv[2][0]=='1') sdsdp[4]=0x19750100; else if (argv[2][0]=='0') sdsdp[4]=0x19750000; if (sdsdp[4]) count += 4; } if (argc > 3) { delay = simple_strtoul(argv[3], NULL, 10); if (delay > 20) delay = 20; sdsdp[4] |= delay; } printf("Writing boot EEPROM ...\n"); if (bootstrap_eeprom_write(CFG_I2C_BOOT_EEPROM_ADDR, 0, (uchar*)sdsdp, count) != 0) printf("bootstrap_eeprom_write failed\n"); else printf("done (dump via 'i2c md 52 0.1 14')\n"); return 0; } U_BOOT_CMD( sbe, 4, 0, do_setup_bootstrap_eeprom, "sbe - setup bootstrap eeprom\n", " [ []]" ); #if defined(CONFIG_PRAM) #include extern env_t *env_ptr; int do_painit(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) { u32 memsize; u32 pram, env_base; char *v; u32 param; ulong *lptr; memsize = gd->bd->bi_memsize; v = getenv("pram"); if (v) pram = simple_strtoul(v, NULL, 10); else { printf("Error: pram undefined. Please define pram in KiB\n"); return 1; } param = memsize - (pram << 10); printf("PARAM: @%08x\n", param); memset((void*)param, 0, (pram << 10)); env_base = memsize - 4096 - ((CFG_ENV_SIZE + 4096) & ~(4096-1)); memcpy((void*)env_base, env_ptr, CFG_ENV_SIZE); lptr = (ulong*)memsize; *(--lptr) = CFG_ENV_SIZE; *(--lptr) = memsize - env_base; *(--lptr) = crc32(0, (void*)(memsize - 0x08), 0x08); *(--lptr) = 0; /* make sure data can be accessed through PCI */ flush_dcache_range(param, param + (pram << 10) - 1); return 0; } U_BOOT_CMD( painit, 1, 1, do_painit, "painit - prepare PciAccess system\n", NULL ); #endif /* CONFIG_PRAM */ int do_selfreset(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) { if (argc > 1) { if (argv[1][0] == '0') { /* assert */ printf("self-reset# asserted\n"); out_be32((void*)GPIO0_TCR, in_be32((void*)GPIO0_TCR) | GPIO0_SELF_RST); } else { /* deassert */ printf("self-reset# deasserted\n"); out_be32((void*)GPIO0_TCR, in_be32((void*)GPIO0_TCR) & ~GPIO0_SELF_RST); } } else { printf("self-reset# is %s\n", in_be32((void*)GPIO0_TCR) & GPIO0_SELF_RST ? "active" : "inactive"); } return 0; } U_BOOT_CMD( selfreset, 2, 1, do_selfreset, "selfreset- assert self-reset# signal\n", NULL ); int do_resetout(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) { pmc440_fpga_t *fpga = (pmc440_fpga_t *)FPGA_BA; /* requiers bootet FPGA and PLD_IOEN_N active */ if (in_be32((void*)GPIO1_OR) & GPIO1_IOEN_N) { printf("Error: resetout requires a bootet FPGA\n"); return -1; } if (argc > 1) { if (argv[1][0] == '0') { /* assert */ printf("PMC-RESETOUT# asserted\n"); FPGA_OUT32(&fpga->hostctrl, HOSTCTRL_PMCRSTOUT_GATE); } else { /* deassert */ printf("PMC-RESETOUT# deasserted\n"); FPGA_OUT32(&fpga->hostctrl, HOSTCTRL_PMCRSTOUT_GATE | HOSTCTRL_PMCRSTOUT_FLAG); } } else { printf("PMC-RESETOUT# is %s\n", FPGA_IN32(&fpga->hostctrl) & HOSTCTRL_PMCRSTOUT_FLAG ? "inactive" : "active"); } return 0; } U_BOOT_CMD( resetout, 2, 1, do_resetout, "resetout - assert PMC-RESETOUT# signal\n", NULL ); int do_inta(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) { if (is_monarch()) { printf("This command is only supported in non-monarch mode\n"); return -1; } if (argc > 1) { if (argv[1][0] == '0') { /* assert */ printf("inta# asserted\n"); out_be32((void*)GPIO1_TCR, in_be32((void*)GPIO1_TCR) | GPIO1_INTA_FAKE); } else { /* deassert */ printf("inta# deasserted\n"); out_be32((void*)GPIO1_TCR, in_be32((void*)GPIO1_TCR) & ~GPIO1_INTA_FAKE); } } else { printf("inta# is %s\n", in_be32((void*)GPIO1_TCR) & GPIO1_INTA_FAKE ? "active" : "inactive"); } return 0; } U_BOOT_CMD( inta, 2, 1, do_inta, "inta - Assert/Deassert or query INTA# state in non-monarch mode\n", NULL ); /* test-only */ int do_pmm(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) { ulong pciaddr; if (argc > 1) { pciaddr = simple_strtoul(argv[1], NULL, 16); pciaddr &= 0xf0000000; /* map PCI address at 0xc0000000 in PLB space */ out32r(PCIX0_PMM1MA, 0x00000000); /* PMM1 Mask/Attribute - disabled b4 setting */ out32r(PCIX0_PMM1LA, 0xc0000000); /* PMM1 Local Address */ out32r(PCIX0_PMM1PCILA, pciaddr); /* PMM1 PCI Low Address */ out32r(PCIX0_PMM1PCIHA, 0x00000000); /* PMM1 PCI High Address */ out32r(PCIX0_PMM1MA, 0xf0000001); /* 256MB + No prefetching, and enable region */ } else { printf("Usage:\npmm %s\n", cmdtp->help); } return 0; } U_BOOT_CMD( pmm, 2, 1, do_pmm, "pmm - Setup pmm[1] registers\n", " (pciaddr will be aligned to 256MB)\n" ); #if defined(CFG_EEPROM_WREN) int do_eep_wren(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) { int query = argc == 1; int state = 0; if (query) { /* Query write access state. */ state = eeprom_write_enable(CFG_I2C_EEPROM_ADDR, -1); if (state < 0) { puts("Query of write access state failed.\n"); } else { printf("Write access for device 0x%0x is %sabled.\n", CFG_I2C_EEPROM_ADDR, state ? "en" : "dis"); state = 0; } } else { if ('0' == argv[1][0]) { /* Disable write access. */ state = eeprom_write_enable(CFG_I2C_EEPROM_ADDR, 0); } else { /* Enable write access. */ state = eeprom_write_enable(CFG_I2C_EEPROM_ADDR, 1); } if (state < 0) { puts("Setup of write access state failed.\n"); } } return state; } U_BOOT_CMD(eepwren, 2, 0, do_eep_wren, "eepwren - Enable / disable / query EEPROM write access\n", NULL); #endif /* #if defined(CFG_EEPROM_WREN) */ #endif /* CONFIG_CMD_BSP */