ppc4xx: Add FPGA support and BSP commands for PMC440 boards
PATCH RESEND 2/3 ppc4xx: Add FPGA support and BSP commands for PMC440 boards
This patch adds some BSP commands and FPGA booting support for esd's PMC440 boards.
Signed-off-by Matthias Fuchs <[email protected]>
---
board/esd/pmc440/cmd_pmc440.c | 559 ++++++++++++++++++++++++++++++++++
board/esd/pmc440/fpga.c | 471 ++++++++++++++++++++++++++++
board/{gen860t => esd/pmc440}/fpga.h | 20 +-
3 files changed, 1041 insertions(+), 9 deletions(-)
create mode 100644 board/esd/pmc440/cmd_pmc440.c
create mode 100644 board/esd/pmc440/fpga.c
copy board/{gen860t => esd/pmc440}/fpga.h (71%)board/esd/pmc440/cmd_pmc440.c new file +559 -0
@@ -0,0 +1,559 @@ +/* +* (C) Copyright 2007 +* Matthias Fuchs, esd Gmbh, matthias.fuchs at 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 <common.h> +#include <command.h> +#include <asm/io.h> +#include <asm/cache.h> +#include <asm/processor.h> + +#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 ; + +#ifdef 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 ; i<FIFO_COUNT ; i++) { + ctrl =FPGA_IN32 (&fpga->fifo[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 ; i<FIFO_COUNT ; i++) +dump_fifo (fpga, i, &n); + + }else if (!strcmp (argv[1 ],"wait" )) { + got_fifoirq =0 ; + +irq_install_handler (IRQ0_FPGA , + (interrupt_handler_t *)fpga_interrupt, + fpga); + +printf (" # fifo level data\n" ); +printf ("______________________________\n" ); + +/* enable all fifo interrupts */ +FPGA_OUT32 (&fpga->hostctrl, +HOSTCTRL_FIFOIE_GATE |HOSTCTRL_FIFOIE_FLAG ); +for (i=0 ; i<FIFO_COUNT ; i++) { +/* enable interrupts from all fifos */ +FPGA_SETBITS (&fpga->fifo[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 ; i<FIFO_COUNT ; i++) +dump_fifo (fpga, i, &n); + + got_fifoirq =0 ; +/* unmask global fifo irq */ +FPGA_OUT32 (&fpga->hostctrl, +HOSTCTRL_FIFOIE_GATE |HOSTCTRL_FIFOIE_FLAG ); + } + } + +/* disable all fifo interrupts */ +FPGA_OUT32 (&fpga->hostctrl,HOSTCTRL_FIFOIE_GATE ); +for (i=0 ; i<FIFO_COUNT ; i++) +FPGA_CLRBITS (&fpga->fifo[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 ; i<n; i++) +FPGA_OUT32 (&fpga->fifo[f].data, data); + }else { +printf ("writing %d x %08x to fifo port at address %08x\n" , + n, data, f); +for (i=0 ; i<n; i++) +out32 (f, data); + } + }else { +printf ("Usage:\nfifo %s\n" , cmdtp->help); +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" , +"<cpufreq:400|533|667> [<console-uart:0|1> [<bringup delay (0..20s)>]]" + ); + + +#ifdef CONFIG_PRAM +#include <environment.h> +extern env_t *env_ptr; + +int do_painit (cmd_tbl_t *cmdtp,int flag,int argc,char *argv[]) +{ +DECLARE_GLOBAL_DATA_PTR ; +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> (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 */
board/esd/pmc440/fpga.c new file +471 -0
471 lines not on this page · raw message
board/esd/pmc440/fpga.h renamed from board/gen860t/fpga.h +11 -9
@@ -1,7 +1,6 @@/* -* (C) Copyright 2002 -* Rich Ireland, Enterasys Networks, rireland at enterasys.com. -* Keith Outwater, keith_outwater at mvis.com. +* (C) Copyright 2007 +* Matthias Fuchs, esd gmbh germany, matthias.fuchs at esd-electronics.com * * See file CREDITS for list of people who contributed to this * project.
@@ -20,14 +19,10 @@* along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA -* */ -/* -* Virtex2 FPGA configuration support for the GEN860T computer -*/ +extern int pmc440_init_fpga (void ); -extern int gen860t_init_fpga (void );extern int fpga_pgm_fn (int assert_pgm,int flush,int cookie);extern int fpga_init_fn (int cookie);extern int fpga_err_fn (int cookie);
@@ -35,6 +30,7 @@ extern int fpga_done_fn(int cookie);extern int fpga_clk_fn (int assert_clk,int flush,int cookie);extern int fpga_cs_fn (int assert_cs,int flush,int cookie);extern int fpga_wr_fn (int assert_write,int flush,int cookie); +extern int fpga_wdata_fn (uchar data,int flush,int cookie);extern int fpga_read_data_fn (unsigned char *data,int cookie);extern int fpga_write_data_fn (unsigned char data,int flush,int cookie);extern int fpga_busy_fn (int cookie);
@@ -42,4 +38,10 @@ extern int fpga_abort_fn(int cookie );extern int fpga_pre_config_fn (int cookie );extern int fpga_post_config_fn (int cookie ); -/* vim: set ts=4 sw=4 tw=78: */ +extern int ngcc_fpga_pgm_fn (int assert_pgm,int flush,int cookie); +extern int ngcc_fpga_init_fn (int cookie); +extern int ngcc_fpga_done_fn (int cookie); +extern int ngcc_fpga_clk_fn (int assert_clk,int flush,int cookie); +extern int ngcc_fpga_wr_fn (int assert_write,int flush,int cookie); +extern int ngcc_fpga_pre_config_fn (int cookie ); +extern int ngcc_fpga_post_config_fn (int cookie );
Signature · 1 line
1.5.3