MIPS: Loongson 2F: Fix of problems introduced by -mfix-loongson2f-jump
authorWu Zhangjin <wuzhangjin@gmail.com>
Sat, 10 Apr 2010 12:07:13 +0000 (20:07 +0800)
committerRalf Baechle <ralf@linux-mips.org>
Fri, 30 Apr 2010 19:52:58 +0000 (20:52 +0100)
The -mfix-loongson2f-jump option provided by latest CVS binutils have fixed
the out-of-order issue of Loongson-2F described in chapter 15 of the
Loongson2F User Manual [1, 2], but introduced some problems.

The option changes all of the jump target to "addr & 0xcfffffff" through the
at($1) register, but for the reboot address of Loongson 2F 0xbfc00000 this is
wrong.  Avoids the problem via telling the assembler to not use the $at
register.

[1] Loongson2F User Manual (Chinese Version)
    http://www.loongson.cn/uploadfile/file/200808211
[2] English Version of Chapter 15:
    http://groups.google.com.hk/group/loongson-dev/msg/e0d2e220958f10a6?dmode=source

Reported-and-tested-by: Liu Shiwei <liushiwei@gmail.com>
Signed-off-by: Wu Zhangjin <wuzhangjin@gmail.com>
Cc: linux-mips <linux-mips@linux-mips.org>
Patchwork: http://patchwork.linux-mips.org/patch/1109/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
arch/mips/loongson/common/reset.c

index 4bd9c18b07a533c087d21f01276b43a65a592950..9e10d6225d9bca134931d2da11d0ba63da784972 100644 (file)
 
 #include <loongson.h>
 
+static inline void loongson_reboot(void)
+{
+#ifndef CONFIG_CPU_JUMP_WORKAROUNDS
+       ((void (*)(void))ioremap_nocache(LOONGSON_BOOT_BASE, 4)) ();
+#else
+       void (*func)(void);
+
+       func = (void *)ioremap_nocache(LOONGSON_BOOT_BASE, 4);
+
+       __asm__ __volatile__(
+       "       .set    noat                                            \n"
+       "       jr      %[func]                                         \n"
+       "       .set    at                                              \n"
+       : /* No outputs */
+       : [func] "r" (func));
+#endif
+}
+
 static void loongson_restart(char *command)
 {
        /* do preparation for reboot */
        mach_prepare_reboot();
 
        /* reboot via jumping to boot base address */
-       ((void (*)(void))ioremap_nocache(LOONGSON_BOOT_BASE, 4)) ();
+       loongson_reboot();
 }
 
 static void loongson_poweroff(void)