obj-$(CONFIG_PPC32)            += entry_32.o setup_32.o
 obj-$(CONFIG_PPC64)            += dma-iommu.o iommu.o
 obj-$(CONFIG_KGDB)             += kgdb.o
-obj-$(CONFIG_PPC_OF_BOOT_TRAMPOLINE)   += prom_init.o
 obj-$(CONFIG_MODULES)          += ppc_ksyms.o
 obj-$(CONFIG_BOOTX_TEXT)       += btext.o
 obj-$(CONFIG_SMP)              += smp.o
 extra-$(CONFIG_PPC_FPU)                += fpu.o
 extra-$(CONFIG_ALTIVEC)                += vector.o
 extra-$(CONFIG_PPC64)          += entry_64.o
+extra-$(CONFIG_PPC_OF_BOOT_TRAMPOLINE) += prom_init.o
 
 extra-y                                += systbl_chk.i
 $(obj)/systbl.o:               systbl_chk
 
  * is running at whatever address it has been loaded at.
  * On ppc32 we compile with -mrelocatable, which means that references
  * to extern and static variables get relocated automatically.
- * On ppc64 we have to relocate the references explicitly with
- * RELOC.  (Note that strings count as static variables.)
+ * ppc64 objects are always relocatable, we just need to relocate the
+ * TOC.
  *
  * Because OF may have mapped I/O devices into the area starting at
  * KERNELBASE, particularly on CHRP machines, we can't safely call
  * On ppc64, 64 bit values are truncated to 32 bits (and
  * fortunately don't get interpreted as two arguments).
  */
+#define RELOC(x)       (x)
+#define ADDR(x)                (u32)(unsigned long)(x)
+
 #ifdef CONFIG_PPC64
-#define RELOC(x)        (*PTRRELOC(&(x)))
-#define ADDR(x)                (u32) add_reloc_offset((unsigned long)(x))
 #define OF_WORKAROUNDS 0
 #else
-#define RELOC(x)       (x)
-#define ADDR(x)                (u32) (x)
 #define OF_WORKAROUNDS of_workarounds
 int of_workarounds;
 #endif
        struct prom_t *_prom = &RELOC(prom);
 
        va_start(args, format);
-#ifdef CONFIG_PPC64
-       format = PTRRELOC(format);
-#endif
        for (p = format; *p != 0; p = q) {
                for (q = p; *q != 0 && *q != '\n' && *q != '%'; ++q)
                        ;
 
 static void __init __attribute__((noreturn)) prom_panic(const char *reason)
 {
-#ifdef CONFIG_PPC64
-       reason = PTRRELOC(reason);
-#endif
        prom_print(reason);
        /* Do not call exit because it clears the screen on pmac
         * it also causes some sort of double-fault on early pmacs */
                 * (we assume this is the same for all cores) and use it to
                 * divide NR_CPUS.
                 */
-               cores = (u32 *)PTRRELOC(&ibm_architecture_vec[IBM_ARCH_VEC_NRCORES_OFFSET]);
+               cores = (u32 *)&ibm_architecture_vec[IBM_ARCH_VEC_NRCORES_OFFSET];
                if (*cores != NR_CPUS) {
                        prom_printf("WARNING ! "
                                    "ibm_architecture_vec structure inconsistent: %lu!\n",
 #endif /* CONFIG_BLK_DEV_INITRD */
 }
 
+#ifdef CONFIG_PPC64
+#ifdef CONFIG_RELOCATABLE
+static void reloc_toc(void)
+{
+}
+
+static void unreloc_toc(void)
+{
+}
+#else
+static void __reloc_toc(void *tocstart, unsigned long offset,
+                       unsigned long nr_entries)
+{
+       unsigned long i;
+       unsigned long *toc_entry = (unsigned long *)tocstart;
+
+       for (i = 0; i < nr_entries; i++) {
+               *toc_entry = *toc_entry + offset;
+               toc_entry++;
+       }
+}
+
+static void reloc_toc(void)
+{
+       unsigned long offset = reloc_offset();
+       unsigned long nr_entries =
+               (__prom_init_toc_end - __prom_init_toc_start) / sizeof(long);
+
+       /* Need to add offset to get at __prom_init_toc_start */
+       __reloc_toc(__prom_init_toc_start + offset, offset, nr_entries);
+
+       mb();
+}
+
+static void unreloc_toc(void)
+{
+       unsigned long offset = reloc_offset();
+       unsigned long nr_entries =
+               (__prom_init_toc_end - __prom_init_toc_start) / sizeof(long);
+
+       mb();
+
+       /* __prom_init_toc_start has been relocated, no need to add offset */
+       __reloc_toc(__prom_init_toc_start, -offset, nr_entries);
+}
+#endif
+#endif
 
 /*
  * We enter here early on, when the Open Firmware prom is still
 #ifdef CONFIG_PPC32
        unsigned long offset = reloc_offset();
        reloc_got2(offset);
+#else
+       reloc_toc();
 #endif
 
        _prom = &RELOC(prom);
 
 #ifdef CONFIG_PPC32
        reloc_got2(-offset);
+#else
+       unreloc_toc();
 #endif
 
 #ifdef CONFIG_PPC_EARLY_DEBUG_OPAL