support for JTAGWAIT.PRG (configure FPGA from JTAG port) implemented

This commit is contained in:
Markus Fröschle
2014-08-09 13:07:28 +00:00
parent f55cae6c0f
commit fd72b7ce9e
7 changed files with 138 additions and 76 deletions

View File

@@ -229,3 +229,6 @@ COPYING.LESSER
dump.bdm dump.bdm
mcf5474.gdb mcf5474.gdb
Makefile Makefile
tos/jtagwait/Makefile
tos/jtagwait/sources/jtagwait.c
tos/jtagwait/include/driver_vec.h

View File

@@ -236,6 +236,7 @@ SECTIONS
* and shouldn't be overwritten on boot * and shouldn't be overwritten on boot
*/ */
__FPGA_JTAG_LOADED = __RAMBAR1; __FPGA_JTAG_LOADED = __RAMBAR1;
__FPGA_JTAG_VALID = __RAMBAR1 + 4;
/* system variables */ /* system variables */
/* RAMBAR0 0 to 0x7FF -> exception vectors */ /* RAMBAR0 0 to 0x7FF -> exception vectors */

View File

@@ -50,6 +50,8 @@ extern uint8_t _FPGA_CONFIG_SIZE[];
* been loaded through JTAG. init_fpga() will honour this and not overwrite config. * been loaded through JTAG. init_fpga() will honour this and not overwrite config.
*/ */
extern bool _FPGA_JTAG_LOADED; extern bool _FPGA_JTAG_LOADED;
extern long _FPGA_JTAG_VALID;
#define VALID_JTAG 0xaffeaffe
void config_gpio_for_fpga_config(void) void config_gpio_for_fpga_config(void)
{ {
@@ -91,10 +93,10 @@ bool init_fpga(void)
volatile int32_t time, start, end; volatile int32_t time, start, end;
int i; int i;
dbg("FPGA load config (_FPGA_JTAG_LOADED = %x)...", _FPGA_JTAG_LOADED); dbg("FPGA load config\r\n(_FPGA_JTAG_LOADED = %x, _FPGA_JTAG_VALID = %x)...\r\n", _FPGA_JTAG_LOADED, _FPGA_JTAG_VALID);
if (_FPGA_JTAG_LOADED == 1) if (_FPGA_JTAG_LOADED == true)
{ {
dbg("detected _FPGA_JTAG_LOADED flag. Not overwriting FPGA config.\r\n"); dbg("detected _FPGA_JTAG_LOADED flag. Not overwriting FPGA config.\r\n");
/* reset the flag so that next boot will load config again from flash */ /* reset the flag so that next boot will load config again from flash */
_FPGA_JTAG_LOADED = 0; _FPGA_JTAG_LOADED = 0;

View File

@@ -244,7 +244,7 @@ void init_serial(void)
MCF_PSC0_PSCOPSET = 0x01; MCF_PSC0_PSCOPSET = 0x01;
MCF_PSC0_PSCCR = 0x05; MCF_PSC0_PSCCR = 0x05;
#ifdef MACHINE_FIREBEE /* PSC3 is not connected to anything on the LITE board */ #if defined(MACHINE_FIREBEE) /* PSC3 is not connected to anything on the LITE board */
/* PSC3: PIC */ /* PSC3: PIC */
MCF_PSC3_PSCSICR = 0; // UART MCF_PSC3_PSCSICR = 0; // UART
MCF_PSC3_PSCCSR = 0xDD; MCF_PSC3_PSCCSR = 0xDD;
@@ -480,7 +480,11 @@ void wait_pll(void)
} while ((* (volatile int16_t *) 0xf0000800 < 0) && MCF_SLT0_SCNT > trgt); } while ((* (volatile int16_t *) 0xf0000800 < 0) && MCF_SLT0_SCNT > trgt);
} }
static volatile uint8_t *pll_base = (volatile uint8_t *) 0xf0000600;
volatile uint8_t *pll_base = (volatile uint8_t *) 0xf0000600;
//#define _OLD_CODE_ /* use old PLL initialization code */
#ifndef _OLD_CODE_
/* /*
* the altpll_reconfig component is connected to the Bus as follows: * the altpll_reconfig component is connected to the Bus as follows:
@@ -562,7 +566,7 @@ struct pll_init
int data; int data;
}; };
static struct pll_init pll_values[] = struct pll_init pll_values[] =
{ {
{ PLL_COUNTER_TYPE_CPLF, PLL_COUNTER_PARAM_LF_R, 27 }, /* loopfilter R */ { PLL_COUNTER_TYPE_CPLF, PLL_COUNTER_PARAM_LF_R, 27 }, /* loopfilter R */
{ PLL_COUNTER_TYPE_CPLF, PLL_COUNTER_PARAM_LF_C, 1 }, /* charge pump 1 */ { PLL_COUNTER_TYPE_CPLF, PLL_COUNTER_PARAM_LF_C, 1 }, /* charge pump 1 */
@@ -576,9 +580,9 @@ static struct pll_init pll_values[] =
{ PLL_COUNTER_TYPE_M, PLL_COUNTER_PARAM_MODE, 1 }, /* M odd division */ { PLL_COUNTER_TYPE_M, PLL_COUNTER_PARAM_MODE, 1 }, /* M odd division */
{ PLL_COUNTER_TYPE_M, PLL_COUNTER_PARAM_LC, 1 }, /* M low = 1 */ { PLL_COUNTER_TYPE_M, PLL_COUNTER_PARAM_LC, 1 }, /* M low = 1 */
{ PLL_COUNTER_TYPE_M, PLL_COUNTER_PARAM_HC, 145 } /* M high = 145 = 146 MHz */ { PLL_COUNTER_TYPE_M, PLL_COUNTER_PARAM_HC, 145 } /* M high = 145 = 146 MHz */
}; };
static int num_pll_values = sizeof(pll_values) / sizeof(struct pll_init); int num_pll_values = sizeof(pll_values) / sizeof(struct pll_init);
#endif /* _OLD_CODE_ */
void init_pll(void) void init_pll(void)
{ {
@@ -586,11 +590,52 @@ void init_pll(void)
xprintf("FPGA PLL initialization: "); xprintf("FPGA PLL initialization: ");
#ifndef _OLD_CODE_
for (i = 0; i < num_pll_values; i++) for (i = 0; i < num_pll_values; i++)
{ {
pll_write(pll_values[i].type, pll_values[i].param, pll_values[i].data); pll_write(pll_values[i].type, pll_values[i].param, pll_values[i].data);
} }
#else /* _OLD_CODE_ */
wait_pll();
* (volatile uint16_t *) (pll_base + 0x48) = 27; /* loopfilter r */
wait_pll();
* (volatile uint16_t *) (pll_base + 0x08) = 1; /* charge pump 1 */
wait_pll();
* (volatile uint16_t *) (pll_base + 0x00) = 12; /* N counter high = 12 */
wait_pll();
* (volatile uint16_t *) (pll_base + 0x40) = 12; /* N counter low = 12 */
wait_pll();
* (volatile uint16_t *) (pll_base + 0x114) = 1; /* ck1 bypass */
wait_pll();
* (volatile uint16_t *) (pll_base + 0x118) = 1; /* ck2 bypass */
wait_pll();
* (volatile uint16_t *) (pll_base + 0x11c) = 1; /* ck3 bypass */
wait_pll();
* (volatile uint16_t *) (pll_base + 0x10) = 1; /* ck0 high = 1 */
wait_pll();
* (volatile uint16_t *) (pll_base + 0x50) = 1; /* ck0 low = 1 */
wait_pll();
* (volatile uint16_t *) (pll_base + 0x144) = 1; /* M odd division */
wait_pll();
* (volatile uint16_t *) (pll_base + 0x44) = 1; /* M low = 1 */
wait_pll();
* (volatile uint16_t *) (pll_base + 0x04) = 145; /* M high = 145 = 146 MHz */
wait_pll();
#endif /* _OLD_CODE_ */
* (volatile uint8_t *) 0xf0000800 = 0; /* set */ * (volatile uint8_t *) 0xf0000800 = 0; /* set */
xprintf("finished\r\n"); xprintf("finished\r\n");
@@ -629,7 +674,7 @@ void init_video_ddr(void) {
_VRAM = 0000070022; /* load MR dll on */ _VRAM = 0000070022; /* load MR dll on */
NOP(); NOP();
* (uint32_t *) 0xf0000400 = 0x01070002; /* fifo on, refresh on, ddrcs und cke on, video dac on */ * (uint32_t *) 0xf0000400 = 0x01070002; /* fifo on, refresh on, ddrcs and cke on, video dac on */
xprintf("finished\r\n"); xprintf("finished\r\n");
} }
@@ -655,19 +700,19 @@ void init_usb(void)
if (handle > 0) if (handle > 0)
{ {
uint32_t id = 0; uint32_t id = 0;
uint32_t class = 0; uint32_t pci_class = 0;
id = pci_read_config_longword(handle, PCIIDR); id = pci_read_config_longword(handle, PCIIDR);
class = pci_read_config_longword(handle, PCIREV); pci_class = pci_read_config_longword(handle, PCIREV);
if (PCI_CLASS_CODE(class) == PCI_CLASS_SERIAL_USB) if (PCI_CLASS_CODE(pci_class) == PCI_CLASS_SERIAL_USB)
{ {
xprintf("serial USB found at bus=0x%x, dev=0x%x, fnc=0x%x (0x%x)\r\n", xprintf("serial USB found at bus=0x%x, dev=0x%x, fnc=0x%x (0x%x)\r\n",
PCI_BUS_FROM_HANDLE(handle), PCI_BUS_FROM_HANDLE(handle),
PCI_DEVICE_FROM_HANDLE(handle), PCI_DEVICE_FROM_HANDLE(handle),
PCI_FUNCTION_FROM_HANDLE(handle), PCI_FUNCTION_FROM_HANDLE(handle),
handle); handle);
if (PCI_SUBCLASS(class) == PCI_CLASS_SERIAL_USB_EHCI) if (PCI_SUBCLASS(pci_class) == PCI_CLASS_SERIAL_USB_EHCI)
{ {
board = ehci_usb_pci_table; board = ehci_usb_pci_table;
while (board->vendor) while (board->vendor)
@@ -682,7 +727,7 @@ void init_usb(void)
board++; board++;
} }
} }
if (PCI_SUBCLASS(class) == PCI_CLASS_SERIAL_USB_OHCI) if (PCI_SUBCLASS(pci_class) == PCI_CLASS_SERIAL_USB_OHCI)
{ {
board = ohci_usb_pci_table; board = ohci_usb_pci_table;
while (board->vendor) while (board->vendor)
@@ -1176,9 +1221,9 @@ void initialize_hardware(void)
video_init(); video_init();
/* do not try to init USB for now on the Firebee, it hangs the machine */ /* do not try to init USB for now on the Firebee, it hangs the machine */
#ifndef MACHINE_FIREBEE //#ifndef MACHINE_FIREBEE
//init_usb(); init_usb();
#endif //#endif
#if MACHINE_FIREBEE #if MACHINE_FIREBEE
init_ac97(); init_ac97();

View File

@@ -33,9 +33,13 @@ APP=jtagwait.prg
TEST_APP=$(APP) TEST_APP=$(APP)
CFLAGS=\ CFLAGS=\
-Os\ -O0\
-g\ -g\
-Wl,-Map,mapfile\ -Wl,-Map,mapfile\
-Wl,--defsym -Wl,__MBAR=0xff000000\
-Wl,--defsym -Wl,__MMUBAR=0xff040000\
-Wl,--defsym -Wl,__FPGA_JTAG_LOADED=0xff101000\
-Wl,--defsym -Wl,__FPGA_JTAG_VALID=0xff101004\
-Wall -Wall
SRCDIR=sources SRCDIR=sources
@@ -43,8 +47,10 @@ INCDIR=include
INCLUDE+=-I$(INCDIR) INCLUDE+=-I$(INCDIR)
CSRCS=\ CSRCS=\
$(SRCDIR)/jtagwait.c $(SRCDIR)/jtagwait.c \
ASRCS= $(SRCDIR)/bas_printf.c
ASRCS=$(SRCDIR)/printf_helper.S
COBJS=$(patsubst $(SRCDIR)/%.o,%.o,$(patsubst %.c,%.o,$(CSRCS))) COBJS=$(patsubst $(SRCDIR)/%.o,%.o,$(patsubst %.c,%.o,$(CSRCS)))
AOBJS=$(patsubst $(SRCDIR)/%.o,%.o,$(patsubst %.S,%.o,$(ASRCS))) AOBJS=$(patsubst $(SRCDIR)/%.o,%.o,$(patsubst %.S,%.o,$(ASRCS)))

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject> <!DOCTYPE QtCreatorProject>
<!-- Written by QtCreator 3.0.1, 2014-08-04T18:51:58. --> <!-- Written by QtCreator 3.0.1, 2014-08-09T06:49:40. -->
<qtcreator> <qtcreator>
<data> <data>
<variable>ProjectExplorer.Project.ActiveTarget</variable> <variable>ProjectExplorer.Project.ActiveTarget</variable>

View File

@@ -3,73 +3,78 @@
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#include "bas_printf.h"
#include "MCF5475.h"
#include "driver_vec.h" #include "driver_vec.h"
#define FPGA_JTAG_LOADED_FLAG ((volatile bool *) 0xFF101000) extern bool _FPGA_JTAG_LOADED;
extern long _FPGA_JTAG_VALID;
#define VALID_JTAG 0xaffeaffe
#define _MBAR ((volatile uint8_t *) 0xFF000000)
#define MCF_GPIO_PDDR_FEC1L ((volatile uint8_t *)(&_MBAR[0xA17]))
#define MCF_GPIO_PDDR_FEC1L_PDDR_FEC1L4 (0x10)
#define MCF_GPIO_PPDSDR_FEC1L ((volatile uint8_t *)(&_MBAR[0xA27]))
#define FPGA_CONFIG (1 << 2) #define FPGA_CONFIG (1 << 2)
#define FPGA_CONF_DONE (1 << 5) #define FPGA_CONF_DONE (1 << 5)
static inline uint32_t set_ipl(uint32_t ipl)
{
uint32_t ret;
__asm__ __volatile__(
" move.w sr,%[ret]\r\n" /* retrieve status register */
" andi.l #0x07,%[ipl]\n\t" /* mask out ipl bits on new value */
" lsl.l #8,%[ipl]\n\t" /* shift them to position */
" move.l %[ret],d0\n\t" /* retrieve original value */
" andi.l #0x0000f8ff,d0\n\t" /* clear ipl part */
" or.l %[ipl],d0\n\t" /* or in new value */
" move.w d0,sr\n\t" /* put it in place */
" andi.l #0x0700,%[ret]\r\n" /* mask out ipl bits */
" lsr.l #8,%[ret]\r\n" /* shift them to position */
: [ret] "=&d" (ret) /* output */
: [ipl] "d" (ipl) /* input */
: "d0", "cc" /* clobber */
);
return ret;
}
void wait_for_jtag(void) void wait_for_jtag(void)
{ {
set_ipl(7); /* disable interrupts */ int i;
/*
* configure FEC1L port directions to enable external JTAG configuration download to FPGA
*/
*MCF_GPIO_PDDR_FEC1L = 0 |
MCF_GPIO_PDDR_FEC1L_PDDR_FEC1L4; /* bit 4 = LED => output */
/* all other bits = input */
/*
* now that this GPIO ports have been switched to input, we can poll for FPGA config
* started from the JTAG interface (CONFIGn goes high) and finish (CONF_DONE goes high)
*/
while (*MCF_GPIO_PPDSDR_FEC1L & FPGA_CONFIG); /* wait for JTAG reset */
while (!(*MCF_GPIO_PPDSDR_FEC1L & FPGA_CONFIG)); /* wait for JTAG config load starting */
while (!(*MCF_GPIO_PPDSDR_FEC1L & FPGA_CONF_DONE)); /* wait for JTAG config load finished */
*FPGA_JTAG_LOADED_FLAG = true; /* indicate jtag loaded FPGA config to BaS */ /* set supervisor stack to end of SRAM1 */
__asm__ __volatile__ (
" move #0x2700,sr\n\t" /* disable interrupts */
" move.l #0xff101000 + 0x1000 - 4,d0\n\t" /* 4KB on-chip core SRAM1 */
" move.l d0,sp\n\t" /* set stack pointer */
:
:
: "d0", "cc" /* clobber */
);
/* MCF_EPORT_EPIER = 0x0; /* disable EPORT interrupts */
* reboot after configuration finished MCF_INTC_IMRL = 0xffffffff;
*/ MCF_INTC_IMRH = 0xffffffff; /* disable interrupt controller */
__asm__ __volatile__(
"jmp 0xE0000000\n\t" MCF_MMU_MMUCR &= ~MCF_MMU_MMUCR_EN; /* disable MMU */
);
xprintf("relocated supervisor stack, disabled interrupts and disabled MMU\r\n");
/*
* configure FEC1L port directions to enable external JTAG configuration download to FPGA
*/
MCF_GPIO_PDDR_FEC1L = 0 |
MCF_GPIO_PDDR_FEC1L_PDDR_FEC1L4; /* bit 4 = LED => output */
/* all other bits = input */
xprintf("waiting for JTAG configuration start\r\n");
/*
* now that this GPIO ports have been switched to input, we can poll for FPGA config
* started from the JTAG interface (CONF_DONE goes low) and finish (CONF_DONE goes high)
*/
while ((MCF_GPIO_PPDSDR_FEC1L & FPGA_CONF_DONE)); /* wait for JTAG config load started */
xprintf("waiting for JTAG configuration finished\r\n");
while (!(MCF_GPIO_PPDSDR_FEC1L & FPGA_CONF_DONE)); /* wait for JTAG config load finished */
xprintf("JTAG configuration finished.\r\n");
_FPGA_JTAG_LOADED = true; /* indicate jtag loaded FPGA config to BaS */
_FPGA_JTAG_VALID = VALID_JTAG;
/* wait */
xprintf("wait a little to let things settle...\r\n");
for (i = 0; i < 1000000; i++);
__asm__ __volatile__(
" jmp 0xe0000000\n\t"
: : :
);
} }
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
printf("\033E\r\nFPGA JTAG configuration support\r\n"); printf("\033E\r\nFPGA JTAG configuration support\r\n");
printf("You may now savely load a new FPGA configuration through the JTAG interface\r\n" printf("You may now savely load a new FPGA configuration through the JTAG interface\r\n"
"and your Firebee will reboot once finished using that new configuration.\r\n"); "and your Firebee will reboot once finished using that new configuration.\r\n");
Supexec(wait_for_jtag); Supexec(wait_for_jtag);
return 0; /* just to make the compiler happy, we will never return */ return 0; /* just to make the compiler happy, we will never return */
} }