summaryrefslogtreecommitdiff
path: root/arch/microblaze
diff options
context:
space:
mode:
Diffstat (limited to 'arch/microblaze')
-rw-r--r--arch/microblaze/config.mk2
-rw-r--r--arch/microblaze/cpu/interrupts.c42
-rw-r--r--arch/microblaze/cpu/start.S2
-rw-r--r--arch/microblaze/cpu/timer.c69
-rw-r--r--arch/microblaze/cpu/u-boot.lds1
-rw-r--r--arch/microblaze/include/asm/global_data.h1
-rw-r--r--arch/microblaze/include/asm/microblaze_intc.h11
-rw-r--r--arch/microblaze/include/asm/microblaze_timer.h3
-rw-r--r--arch/microblaze/include/asm/processor.h3
-rw-r--r--arch/microblaze/lib/board.c59
10 files changed, 114 insertions, 79 deletions
diff --git a/arch/microblaze/config.mk b/arch/microblaze/config.mk
index aca79e2..b4935f0 100644
--- a/arch/microblaze/config.mk
+++ b/arch/microblaze/config.mk
@@ -31,3 +31,5 @@ CONFIG_STANDALONE_LOAD_ADDR ?= 0x80F00000
PLATFORM_CPPFLAGS += -ffixed-r31 -D__microblaze__
LDSCRIPT ?= $(SRCTREE)/$(CPUDIR)/u-boot.lds
+
+CONFIG_ARCH_DEVICE_TREE := microblaze
diff --git a/arch/microblaze/cpu/interrupts.c b/arch/microblaze/cpu/interrupts.c
index ee67082..7f2ee64 100644
--- a/arch/microblaze/cpu/interrupts.c
+++ b/arch/microblaze/cpu/interrupts.c
@@ -32,15 +32,12 @@
#undef DEBUG_INT
-extern void microblaze_disable_interrupts (void);
-extern void microblaze_enable_interrupts (void);
-
-void enable_interrupts (void)
+void enable_interrupts(void)
{
MSRSET(0x2);
}
-int disable_interrupts (void)
+int disable_interrupts(void)
{
unsigned int msr;
@@ -58,20 +55,21 @@ microblaze_intc_t *intc;
/* default handler */
static void def_hdlr(void)
{
- puts ("def_hdlr\n");
+ puts("def_hdlr\n");
}
static void enable_one_interrupt(int irq)
{
int mask;
int offset = 1;
+
offset <<= irq;
mask = intc->ier;
intc->ier = (mask | offset);
#ifdef DEBUG_INT
- printf ("Enable one interrupt irq %x - mask %x,ier %x\n", offset, mask,
+ printf("Enable one interrupt irq %x - mask %x,ier %x\n", offset, mask,
intc->ier);
- printf ("INTC isr %x, ier %x, iar %x, mer %x\n", intc->isr, intc->ier,
+ printf("INTC isr %x, ier %x, iar %x, mer %x\n", intc->isr, intc->ier,
intc->iar, intc->mer);
#endif
}
@@ -80,25 +78,26 @@ static void disable_one_interrupt(int irq)
{
int mask;
int offset = 1;
+
offset <<= irq;
mask = intc->ier;
intc->ier = (mask & ~offset);
#ifdef DEBUG_INT
- printf ("Disable one interrupt irq %x - mask %x,ier %x\n", irq, mask,
+ printf("Disable one interrupt irq %x - mask %x,ier %x\n", irq, mask,
intc->ier);
- printf ("INTC isr %x, ier %x, iar %x, mer %x\n", intc->isr, intc->ier,
+ printf("INTC isr %x, ier %x, iar %x, mer %x\n", intc->isr, intc->ier,
intc->iar, intc->mer);
#endif
}
-/* adding new handler for interrupt */
-void install_interrupt_handler (int irq, interrupt_handler_t * hdlr, void *arg)
+int install_interrupt_handler(int irq, interrupt_handler_t *hdlr, void *arg)
{
struct irq_action *act;
+
/* irq out of range */
if ((irq < 0) || (irq > irq_no)) {
- puts ("IRQ out of range\n");
- return;
+ puts("IRQ out of range\n");
+ return -1;
}
act = &vecs[irq];
if (hdlr) { /* enable */
@@ -106,11 +105,14 @@ void install_interrupt_handler (int irq, interrupt_handler_t * hdlr, void *arg)
act->arg = arg;
act->count = 0;
enable_one_interrupt (irq);
- } else { /* disable */
- act->handler = (interrupt_handler_t *) def_hdlr;
- act->arg = (void *)irq;
- disable_one_interrupt (irq);
+ return 0;
}
+
+ /* Disable */
+ act->handler = (interrupt_handler_t *) def_hdlr;
+ act->arg = (void *)irq;
+ disable_one_interrupt(irq);
+ return 1;
}
/* initialization interrupt controller - hardware */
@@ -122,7 +124,7 @@ static void intc_init(void)
/* XIntc_Start - hw_interrupt enable and all interrupt enable */
intc->mer = 0x3;
#ifdef DEBUG_INT
- printf ("INTC isr %x, ier %x, iar %x, mer %x\n", intc->isr, intc->ier,
+ printf("INTC isr %x, ier %x, iar %x, mer %x\n", intc->isr, intc->ier,
intc->iar, intc->mer);
#endif
}
@@ -157,7 +159,7 @@ int interrupts_init(void)
return 0;
}
-void interrupt_handler (void)
+void interrupt_handler(void)
{
int irqs = intc->ivr; /* find active interrupt */
int mask = 1;
diff --git a/arch/microblaze/cpu/start.S b/arch/microblaze/cpu/start.S
index 8a2f634..8564c4e 100644
--- a/arch/microblaze/cpu/start.S
+++ b/arch/microblaze/cpu/start.S
@@ -149,7 +149,7 @@ clear_bss:
cmp r6, r5, r4 /* check if we have reach the end */
bnei r6, 2b
3: /* jumping to board_init */
- brai board_init
+ brai board_init_f
1: bri 1b
/*
diff --git a/arch/microblaze/cpu/timer.c b/arch/microblaze/cpu/timer.c
index cc6b897..1330401 100644
--- a/arch/microblaze/cpu/timer.c
+++ b/arch/microblaze/cpu/timer.c
@@ -27,42 +27,30 @@
#include <asm/microblaze_intc.h>
volatile int timestamp = 0;
+microblaze_timer_t *tmr;
-#ifdef CONFIG_SYS_TIMER_0
ulong get_timer (ulong base)
{
- return (timestamp - base);
+ if (tmr)
+ return timestamp - base;
+ return timestamp++ - base;
}
-#else
-ulong get_timer (ulong base)
-{
- return (timestamp++ - base);
-}
-#endif
-#ifdef CONFIG_SYS_TIMER_0
void __udelay(unsigned long usec)
{
- int i;
+ u32 i;
- i = get_timer(0);
- while ((get_timer(0) - i) < (usec / 1000))
- ;
+ if (tmr) {
+ i = get_timer(0);
+ while ((get_timer(0) - i) < (usec / 1000))
+ ;
+ } else {
+ for (i = 0; i < (usec * XILINX_CLOCK_FREQ / 10000000); i++)
+ ;
+ }
}
-#else
-void __udelay(unsigned long usec)
-{
- unsigned int i;
- for (i = 0; i < (usec * CONFIG_XILINX_CLOCK_FREQ / 10000000); i++)
- ;
-}
-#endif
-
-#ifdef CONFIG_SYS_TIMER_0
-microblaze_timer_t *tmr = (microblaze_timer_t *) (CONFIG_SYS_TIMER_0_ADDR);
-
-void timer_isr (void *arg)
+static void timer_isr(void *arg)
{
timestamp++;
tmr->control = tmr->control | TIMER_INTERRUPT;
@@ -70,15 +58,30 @@ void timer_isr (void *arg)
int timer_init (void)
{
- tmr->loadreg = CONFIG_SYS_TIMER_0_PRELOAD;
- tmr->control = TIMER_INTERRUPT | TIMER_RESET;
- tmr->control =
- TIMER_ENABLE | TIMER_ENABLE_INTR | TIMER_RELOAD | TIMER_DOWN_COUNT;
- timestamp = 0;
- install_interrupt_handler (CONFIG_SYS_TIMER_0_IRQ, timer_isr, (void *)tmr);
+ int irq = -1;
+ u32 preload = 0;
+ u32 ret = 0;
+
+#if defined(CONFIG_SYS_TIMER_0_ADDR) && defined(CONFIG_SYS_INTC_0_NUM)
+ preload = XILINX_CLOCK_FREQ / CONFIG_SYS_HZ;
+ irq = CONFIG_SYS_TIMER_0_IRQ;
+ tmr = (microblaze_timer_t *) (CONFIG_SYS_TIMER_0_ADDR);
+#endif
+
+ if (tmr && preload && irq >= 0) {
+ tmr->loadreg = preload;
+ tmr->control = TIMER_INTERRUPT | TIMER_RESET;
+ tmr->control = TIMER_ENABLE | TIMER_ENABLE_INTR |\
+ TIMER_RELOAD | TIMER_DOWN_COUNT;
+ timestamp = 0;
+ ret = install_interrupt_handler (irq, timer_isr, (void *)tmr);
+ if (ret)
+ tmr = NULL;
+ }
+
+ /* No problem if timer is not found/initialized */
return 0;
}
-#endif
/*
* This function is derived from PowerPC code (read timebase as long long).
diff --git a/arch/microblaze/cpu/u-boot.lds b/arch/microblaze/cpu/u-boot.lds
index ee41145..d033a28 100644
--- a/arch/microblaze/cpu/u-boot.lds
+++ b/arch/microblaze/cpu/u-boot.lds
@@ -45,6 +45,7 @@ SECTIONS
.data ALIGN(0x4):
{
__data_start = .;
+ dts/libdts.o (.data)
*(.data)
__data_end = .;
}
diff --git a/arch/microblaze/include/asm/global_data.h b/arch/microblaze/include/asm/global_data.h
index 0dc4ce9..de3b8db 100644
--- a/arch/microblaze/include/asm/global_data.h
+++ b/arch/microblaze/include/asm/global_data.h
@@ -41,6 +41,7 @@ typedef struct global_data {
unsigned long precon_buf_idx; /* Pre-Console buffer index */
#endif
unsigned long env_addr; /* Address of Environment struct */
+ const void *fdt_blob; /* Our device tree, NULL if none */
unsigned long env_valid; /* Checksum of Environment valid? */
unsigned long fb_base; /* base address of frame buffer */
void **jt; /* jump table */
diff --git a/arch/microblaze/include/asm/microblaze_intc.h b/arch/microblaze/include/asm/microblaze_intc.h
index 6142b9c..e9640f5 100644
--- a/arch/microblaze/include/asm/microblaze_intc.h
+++ b/arch/microblaze/include/asm/microblaze_intc.h
@@ -39,7 +39,16 @@ struct irq_action {
int count; /* number of interrupt */
};
-void install_interrupt_handler (int irq, interrupt_handler_t * hdlr,
+/**
+ * Register and unregister interrupt handler rutines
+ *
+ * @param irq IRQ number
+ * @param hdlr Interrupt handler rutine
+ * @param arg Pointer to argument which is passed to int. handler rutine
+ * @return 0 if registration pass, 1 if unregistration pass,
+ * or an error code < 0 otherwise
+ */
+int install_interrupt_handler(int irq, interrupt_handler_t *hdlr,
void *arg);
int interrupts_init(void);
diff --git a/arch/microblaze/include/asm/microblaze_timer.h b/arch/microblaze/include/asm/microblaze_timer.h
index 844c8db..28e8b02 100644
--- a/arch/microblaze/include/asm/microblaze_timer.h
+++ b/arch/microblaze/include/asm/microblaze_timer.h
@@ -39,3 +39,6 @@ typedef volatile struct microblaze_timer_t {
int loadreg; /* load register TLR */
int counter; /* timer/counter register */
} microblaze_timer_t;
+
+int timer_init(void);
+
diff --git a/arch/microblaze/include/asm/processor.h b/arch/microblaze/include/asm/processor.h
index 2295d0a..2c4d5ff 100644
--- a/arch/microblaze/include/asm/processor.h
+++ b/arch/microblaze/include/asm/processor.h
@@ -28,4 +28,7 @@
extern char __end[];
extern char __text_start[];
+/* Microblaze board initialization function */
+void board_init(void);
+
#endif /* __ASM_MICROBLAZE_PROCESSOR_H */
diff --git a/arch/microblaze/lib/board.c b/arch/microblaze/lib/board.c
index b80250a..674b573 100644
--- a/arch/microblaze/lib/board.c
+++ b/arch/microblaze/lib/board.c
@@ -32,21 +32,13 @@
#include <stdio_dev.h>
#include <serial.h>
#include <net.h>
+#include <linux/compiler.h>
#include <asm/processor.h>
#include <asm/microblaze_intc.h>
+#include <fdtdec.h>
DECLARE_GLOBAL_DATA_PTR;
-#ifdef CONFIG_SYS_GPIO_0
-extern int gpio_init (void);
-#endif
-#ifdef CONFIG_SYS_TIMER_0
-extern int timer_init (void);
-#endif
-#ifdef CONFIG_SYS_FSL_2
-extern void fsl_init2 (void);
-#endif
-
/*
* All attempts to come up with a "common" initialization sequence
* that works for all boards and architectures failed: some of the
@@ -63,31 +55,26 @@ typedef int (init_fnc_t) (void);
init_fnc_t *init_sequence[] = {
env_init,
+#ifdef CONFIG_OF_CONTROL
+ fdtdec_check_fdt,
+#endif
serial_init,
console_init_f,
-#ifdef CONFIG_SYS_GPIO_0
- gpio_init,
-#endif
interrupts_init,
-#ifdef CONFIG_SYS_TIMER_0
timer_init,
-#endif
-#ifdef CONFIG_SYS_FSL_2
- fsl_init2,
-#endif
NULL,
};
unsigned long monitor_flash_len;
-void board_init (void)
+void board_init_f(ulong not_used)
{
bd_t *bd;
init_fnc_t **init_fnc_ptr;
gd = (gd_t *) (CONFIG_SYS_SDRAM_BASE + CONFIG_SYS_GBL_DATA_OFFSET);
bd = (bd_t *) (CONFIG_SYS_SDRAM_BASE + CONFIG_SYS_GBL_DATA_OFFSET \
- GENERATED_BD_INFO_SIZE);
- char *s;
+ __maybe_unused char *s;
#if defined(CONFIG_CMD_FLASH)
ulong flash_size = 0;
#endif
@@ -103,6 +90,17 @@ void board_init (void)
monitor_flash_len = __end - __text_start;
+#ifdef CONFIG_OF_EMBED
+ /* Get a pointer to the FDT */
+ gd->fdt_blob = _binary_dt_dtb_start;
+#elif defined CONFIG_OF_SEPARATE
+ /* FDT is at end of image */
+ gd->fdt_blob = (void *)__end;
+#endif
+ /* Allow the early environment to override the fdt address */
+ gd->fdt_blob = (void *)getenv_ulong("fdtcontroladdr", 16,
+ (uintptr_t)gd->fdt_blob);
+
/*
* The Malloc area is immediately below the monitor copy in DRAM
* aka CONFIG_SYS_MONITOR_BASE - Note there is no need for reloc_off
@@ -121,6 +119,15 @@ void board_init (void)
}
}
+#ifdef CONFIG_OF_CONTROL
+ /* For now, put this check after the console is ready */
+ if (fdtdec_prepare_fdt()) {
+ panic("** CONFIG_OF_CONTROL defined but no FDT - please see "
+ "doc/README.fdt-control");
+ } else
+ printf("DTB: 0x%x\n", (u32)gd->fdt_blob);
+#endif
+
puts ("SDRAM :\n");
printf ("\t\tIcache:%s\n", icache_status() ? "ON" : "OFF");
printf ("\t\tDcache:%s\n", dcache_status() ? "ON" : "OFF");
@@ -129,9 +136,8 @@ void board_init (void)
#if defined(CONFIG_CMD_FLASH)
puts ("Flash: ");
bd->bi_flashstart = CONFIG_SYS_FLASH_BASE;
- if (0 < (flash_size = flash_init ())) {
- bd->bi_flashsize = flash_size;
- bd->bi_flashoffset = CONFIG_SYS_FLASH_BASE + flash_size;
+ flash_size = flash_init();
+ if (bd->bi_flashstart && flash_size > 0) {
# ifdef CONFIG_SYS_FLASH_CHECKSUM
print_size (flash_size, "");
/*
@@ -142,13 +148,16 @@ void board_init (void)
s = getenv ("flashchecksum");
if (s && (*s == 'y')) {
printf (" CRC: %08X",
- crc32 (0, (const unsigned char *) CONFIG_SYS_FLASH_BASE, flash_size)
+ crc32(0, (const u8 *)bd->bi_flashstart,
+ flash_size)
);
}
putc ('\n');
# else /* !CONFIG_SYS_FLASH_CHECKSUM */
print_size (flash_size, "\n");
# endif /* CONFIG_SYS_FLASH_CHECKSUM */
+ bd->bi_flashsize = flash_size;
+ bd->bi_flashoffset = bd->bi_flashstart + flash_size;
} else {
puts ("Flash init FAILED");
bd->bi_flashstart = 0;
@@ -169,6 +178,8 @@ void board_init (void)
/* Initialize the console (after the relocation and devices init) */
console_init_r();
+ board_init();
+
/* Initialize from environment */
load_addr = getenv_ulong("loadaddr", 16, load_addr);