diff --git a/arch/sparc/cpu/leon2/prom.c b/arch/sparc/cpu/leon2/prom.c
index cd2571f0d6e4e72113b9c879911407a98624864b..7829e7abb2e8bc6e1c518e45735ff97eae7e45d8 100644
--- a/arch/sparc/cpu/leon2/prom.c
+++ b/arch/sparc/cpu/leon2/prom.c
@@ -25,6 +25,8 @@ extern struct linux_romvec *kernel_arg_promvec;
 #define PROM_TEXT __attribute__ ((__section__ (".prom.text")))
 #define PROM_DATA __attribute__ ((__section__ (".prom.data")))
 
+void *__prom_start_reloc; /* relocated prom_start address */
+
 /* for __va */
 extern int __prom_start;
 #define PAGE_OFFSET 0xf0000000
diff --git a/arch/sparc/cpu/leon2/start.S b/arch/sparc/cpu/leon2/start.S
index 7362ae134d72c6988a176ed034ec49a341796707..1b404da36291a9305035f54c7c96b143748c4a69 100644
--- a/arch/sparc/cpu/leon2/start.S
+++ b/arch/sparc/cpu/leon2/start.S
@@ -414,24 +414,24 @@ fixup_got:
 	bcs	30b			! while (ptr < end)
 	 nop
 
-#if 0 /* FIXME: Relocated PROM address should be calculated! */
-
 prom_relocate:
 	SPARC_LOAD_ADDRESS(__prom_start, l7, g2)
 	SPARC_LOAD_ADDRESS(__prom_end, l7, g3)
-	set	CONFIG_SYS_PROM_OFFSET, %g4
-
-prom_relocate_loop:
-	ldd	[%g2],%l0
-	ldd	[%g2+8],%l2
-	std	%l0,[%g4]
-	std	%l2,[%g4+8]
-	inc	16,%g2
-	subcc	%g3,%g2,%g0
-	bne	prom_relocate_loop
-	 inc	16,%g4
+	/*
+	 * Calculated addres is stored in this variable by
+	 * reserve_prom() function in common/board_f.c
+	 */
+	SPARC_LOAD_ADDRESS(__prom_start_reloc, l7, g4)
+	ld	[%g4], %g4
 
-#endif
+40:	ldd	[%g2], %l0
+	ldd	[%g2+8], %l2
+	std	%l0, [%g4]
+	std	%l2, [%g4+8]
+	inc	16, %g2
+	cmp	%g2, %g3
+	bcs	40b
+	 inc	16, %g4
 
 ! %o0 = stack pointer (relocated)
 ! %o1 = global data pointer (relocated)
diff --git a/arch/sparc/cpu/leon3/prom.c b/arch/sparc/cpu/leon3/prom.c
index c391be7420cfd9558fc66fcd445462922e41b8fe..1f185b776b48ed9ca43c75f4f3c69cfed67c4483 100644
--- a/arch/sparc/cpu/leon3/prom.c
+++ b/arch/sparc/cpu/leon3/prom.c
@@ -33,6 +33,8 @@ DECLARE_GLOBAL_DATA_PTR;
 
 ambapp_dev_gptimer *gptimer;
 
+void *__prom_start_reloc; /* relocated prom_start address */
+
 /* for __va */
 extern int __prom_start;
 #define PAGE_OFFSET 0xf0000000
diff --git a/arch/sparc/cpu/leon3/start.S b/arch/sparc/cpu/leon3/start.S
index 52e82b5e3317206ff985a1765f3f3087d8970f6f..1527d72a6d79e9838b92064572b643ad205cfc4e 100644
--- a/arch/sparc/cpu/leon3/start.S
+++ b/arch/sparc/cpu/leon3/start.S
@@ -397,24 +397,24 @@ fixup_got:
 	bcs	30b			! while (ptr < end)
 	 nop
 
-#if 0 /* FIXME: Relocated PROM address should be calculated! */
-
 prom_relocate:
 	SPARC_LOAD_ADDRESS(__prom_start, l7, g2)
 	SPARC_LOAD_ADDRESS(__prom_end, l7, g3)
-	set	CONFIG_SYS_PROM_OFFSET, %g4
-
-prom_relocate_loop:
-	ldd	[%g2],%l0
-	ldd	[%g2+8],%l2
-	std	%l0,[%g4]
-	std	%l2,[%g4+8]
-	inc	16,%g2
-	subcc	%g3,%g2,%g0
-	bne	prom_relocate_loop
-	 inc	16,%g4
+	/*
+	 * Calculated addres is stored in this variable by
+	 * reserve_prom() function in common/board_f.c
+	 */
+	SPARC_LOAD_ADDRESS(__prom_start_reloc, l7, g4)
+	ld	[%g4], %g4
 
-#endif
+40:	ldd	[%g2], %l0
+	ldd	[%g2+8], %l2
+	std	%l0, [%g4]
+	std	%l2, [%g4+8]
+	inc	16, %g2
+	cmp	%g2, %g3
+	bcs	40b
+	 inc	16, %g4
 
 ! %o0 = stack pointer (relocated)
 ! %o1 = global data pointer (relocated)
diff --git a/common/board_f.c b/common/board_f.c
index 2dd10b9819c8899ce0df2e6ca7d0ba7566851599..8325dc333c69e44b218378b5fb1bf0b92dedbe97 100644
--- a/common/board_f.c
+++ b/common/board_f.c
@@ -357,6 +357,20 @@ static int setup_dest_addr(void)
 	return 0;
 }
 
+#if defined(CONFIG_SPARC)
+static int reserve_prom(void)
+{
+	/* defined in arch/sparc/cpu/leon?/prom.c */
+	extern void *__prom_start_reloc;
+	int size = 8192; /* page table = 2k, prom = 6k */
+	gd->relocaddr -= size;
+	__prom_start_reloc = map_sysmem(gd->relocaddr + 2048, size - 2048);
+	debug("Reserving %dk for PROM and page table at %08lx\n", size,
+		gd->relocaddr);
+	return 0;
+}
+#endif
+
 #if defined(CONFIG_LOGBUFFER) && !defined(CONFIG_ALT_LB_ADDR)
 static int reserve_logbuffer(void)
 {
@@ -909,6 +923,9 @@ static init_fnc_t init_sequence_f[] = {
 	/* Blackfin u-boot monitor should be on top of the ram */
 	reserve_uboot,
 #endif
+#if defined(CONFIG_SPARC)
+	reserve_prom,
+#endif
 #if defined(CONFIG_LOGBUFFER) && !defined(CONFIG_ALT_LB_ADDR)
 	reserve_logbuffer,
 #endif
diff --git a/common/board_r.c b/common/board_r.c
index f1dfa68fd55f84198be61e31c2cad19f9f6c2461..3bf49fdfb3754d67a423e548990ca7f15999dea2 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -66,6 +66,10 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
+#if defined(CONFIG_SPARC)
+extern int prom_init(void);
+#endif
+
 ulong monitor_flash_len;
 
 __weak int board_flash_wp_on(void)
@@ -933,6 +937,9 @@ init_fnc_t init_sequence_r[] = {
 #endif
 #ifdef CONFIG_PS2KBD
 	initr_kbd,
+#endif
+#if defined(CONFIG_SPARC)
+	prom_init,
 #endif
 	run_main_loop,
 };