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
mcf5474.gdb
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
*/
__FPGA_JTAG_LOADED = __RAMBAR1;
__FPGA_JTAG_VALID = __RAMBAR1 + 4;
/* system variables */
/* 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.
*/
extern bool _FPGA_JTAG_LOADED;
extern long _FPGA_JTAG_VALID;
#define VALID_JTAG 0xaffeaffe
void config_gpio_for_fpga_config(void)
{
@@ -91,10 +93,10 @@ bool init_fpga(void)
volatile int32_t time, start, end;
int i;
dbg("FPGA load config (_FPGA_JTAG_LOADED = %x)...", _FPGA_JTAG_LOADED);
if (_FPGA_JTAG_LOADED == 1)
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 == 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 */
_FPGA_JTAG_LOADED = 0;

View File

@@ -244,7 +244,7 @@ void init_serial(void)
MCF_PSC0_PSCOPSET = 0x01;
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 */
MCF_PSC3_PSCSICR = 0; // UART
MCF_PSC3_PSCCSR = 0xDD;
@@ -480,7 +480,11 @@ void wait_pll(void)
} 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:
@@ -562,7 +566,7 @@ struct pll_init
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_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_LC, 1 }, /* M low = 1 */
{ 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)
{
@@ -586,11 +590,52 @@ void init_pll(void)
xprintf("FPGA PLL initialization: ");
#ifndef _OLD_CODE_
for (i = 0; i < num_pll_values; i++)
{
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 */
xprintf("finished\r\n");
@@ -629,7 +674,7 @@ void init_video_ddr(void) {
_VRAM = 0000070022; /* load MR dll on */
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");
}
@@ -655,19 +700,19 @@ void init_usb(void)
if (handle > 0)
{
uint32_t id = 0;
uint32_t class = 0;
uint32_t pci_class = 0;
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",
PCI_BUS_FROM_HANDLE(handle),
PCI_DEVICE_FROM_HANDLE(handle),
PCI_FUNCTION_FROM_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;
while (board->vendor)
@@ -682,7 +727,7 @@ void init_usb(void)
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;
while (board->vendor)
@@ -1176,9 +1221,9 @@ void initialize_hardware(void)
video_init();
/* do not try to init USB for now on the Firebee, it hangs the machine */
#ifndef MACHINE_FIREBEE
//init_usb();
#endif
//#ifndef MACHINE_FIREBEE
init_usb();
//#endif
#if MACHINE_FIREBEE
init_ac97();

View File

@@ -33,18 +33,24 @@ APP=jtagwait.prg
TEST_APP=$(APP)
CFLAGS=\
-Os\
-O0\
-g\
-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
SRCDIR=sources
INCDIR=include
INCLUDE+=-I$(INCDIR)
CSRCS=\
$(SRCDIR)/jtagwait.c
ASRCS=
$(SRCDIR)/jtagwait.c \
$(SRCDIR)/bas_printf.c
ASRCS=$(SRCDIR)/printf_helper.S
COBJS=$(patsubst $(SRCDIR)/%.o,%.o,$(patsubst %.c,%.o,$(CSRCS)))
AOBJS=$(patsubst $(SRCDIR)/%.o,%.o,$(patsubst %.S,%.o,$(ASRCS)))
@@ -91,7 +97,7 @@ clean:
.PHONY: printvars
printvars:
@$(foreach V,$(.VARIABLES), $(if $(filter-out environment% default automatic, $(origin $V)),$(warning $V=$($V))))
ifneq (clean,$(MAKECMDGOALS))
-include $(DEPEND)
endif

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!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>
<data>
<variable>ProjectExplorer.Project.ActiveTarget</variable>

View File

@@ -3,73 +3,78 @@
#include <stdint.h>
#include <stdbool.h>
#include "bas_printf.h"
#include "MCF5475.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_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)
{
set_ipl(7); /* disable interrupts */
/*
* 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 */
int i;
*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 */
);
/*
* reboot after configuration finished
*/
__asm__ __volatile__(
"jmp 0xE0000000\n\t"
);
MCF_EPORT_EPIER = 0x0; /* disable EPORT interrupts */
MCF_INTC_IMRL = 0xffffffff;
MCF_INTC_IMRH = 0xffffffff; /* disable interrupt controller */
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[])
{
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"
"and your Firebee will reboot once finished using that new configuration.\r\n");
Supexec(wait_for_jtag);
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"
"and your Firebee will reboot once finished using that new configuration.\r\n");
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 */
}