Merge tag 'for-linus' of https://github.com/openrisc/linux
[linux-2.6-microblaze.git] / arch / openrisc / kernel / head.S
index 2fa6cef..e11699f 100644 (file)
        /* temporary store r3, r9 into r1, r10 */               ;\
        l.addi  r1,r3,0x0                                       ;\
        l.addi  r10,r9,0x0                                      ;\
-       /* the string referenced by r3 must be low enough */    ;\
+       LOAD_SYMBOL_2_GPR(r9,_string_unhandled_exception)       ;\
+       tophys  (r3,r9)                                         ;\
        l.jal   _emergency_print                                ;\
-       l.ori   r3,r0,lo(_string_unhandled_exception)           ;\
+        l.nop                                                  ;\
        l.mfspr r3,r0,SPR_NPC                                   ;\
        l.jal   _emergency_print_nr                             ;\
-       l.andi  r3,r3,0x1f00                                    ;\
-       /* the string referenced by r3 must be low enough */    ;\
+        l.andi r3,r3,0x1f00                                    ;\
+       LOAD_SYMBOL_2_GPR(r9,_string_epc_prefix)                ;\
+       tophys  (r3,r9)                                         ;\
        l.jal   _emergency_print                                ;\
-       l.ori   r3,r0,lo(_string_epc_prefix)                    ;\
+        l.nop                                                  ;\
        l.jal   _emergency_print_nr                             ;\
-       l.mfspr r3,r0,SPR_EPCR_BASE                             ;\
+        l.mfspr r3,r0,SPR_EPCR_BASE                            ;\
+       LOAD_SYMBOL_2_GPR(r9,_string_nl)                        ;\
+       tophys  (r3,r9)                                         ;\
        l.jal   _emergency_print                                ;\
-       l.ori   r3,r0,lo(_string_nl)                            ;\
+        l.nop                                                  ;\
        /* end of printing */                                   ;\
        l.addi  r3,r1,0x0                                       ;\
        l.addi  r9,r10,0x0                                      ;\
@@ -1330,274 +1334,110 @@ i_pte_not_present:
 
 /* =================================================[ debugging aids ]=== */
 
-       .align 64
-_immu_trampoline:
-       .space 64
-_immu_trampoline_top:
-
-#define TRAMP_SLOT_0           (0x0)
-#define TRAMP_SLOT_1           (0x4)
-#define TRAMP_SLOT_2           (0x8)
-#define TRAMP_SLOT_3           (0xc)
-#define TRAMP_SLOT_4           (0x10)
-#define TRAMP_SLOT_5           (0x14)
-#define TRAMP_FRAME_SIZE       (0x18)
-
-ENTRY(_immu_trampoline_workaround)
-       // r2 EEA
-       // r6 is physical EEA
-       tophys(r6,r2)
-
-       LOAD_SYMBOL_2_GPR(r5,_immu_trampoline)
-       tophys  (r3,r5)                 // r3 is trampoline (physical)
-
-       LOAD_SYMBOL_2_GPR(r4,0x15000000)
-       l.sw    TRAMP_SLOT_0(r3),r4
-       l.sw    TRAMP_SLOT_1(r3),r4
-       l.sw    TRAMP_SLOT_4(r3),r4
-       l.sw    TRAMP_SLOT_5(r3),r4
-
-                                       // EPC = EEA - 0x4
-       l.lwz   r4,0x0(r6)              // load op @ EEA + 0x0 (fc address)
-       l.sw    TRAMP_SLOT_3(r3),r4     // store it to _immu_trampoline_data
-       l.lwz   r4,-0x4(r6)             // load op @ EEA - 0x4 (f8 address)
-       l.sw    TRAMP_SLOT_2(r3),r4     // store it to _immu_trampoline_data
-
-       l.srli  r5,r4,26                // check opcode for write access
-       l.sfeqi r5,0                    // l.j
-       l.bf    0f
-       l.sfeqi r5,0x11                 // l.jr
-       l.bf    1f
-       l.sfeqi r5,1                    // l.jal
-       l.bf    2f
-       l.sfeqi r5,0x12                 // l.jalr
-       l.bf    3f
-       l.sfeqi r5,3                    // l.bnf
-       l.bf    4f
-       l.sfeqi r5,4                    // l.bf
-       l.bf    5f
-99:
-       l.nop
-       l.j     99b                     // should never happen
-       l.nop   1
-
-       // r2 is EEA
-       // r3 is trampoline address (physical)
-       // r4 is instruction
-       // r6 is physical(EEA)
-       //
-       // r5
-
-2:     // l.jal
-
-       /* 19 20 aa aa  l.movhi r9,0xaaaa
-        * a9 29 bb bb  l.ori   r9,0xbbbb
-        *
-        * where 0xaaaabbbb is EEA + 0x4 shifted right 2
-        */
-
-       l.addi  r6,r2,0x4               // this is 0xaaaabbbb
-
-                                       // l.movhi r9,0xaaaa
-       l.ori   r5,r0,0x1920            // 0x1920 == l.movhi r9
-       l.sh    (TRAMP_SLOT_0+0x0)(r3),r5
-       l.srli  r5,r6,16
-       l.sh    (TRAMP_SLOT_0+0x2)(r3),r5
-
-                                       // l.ori   r9,0xbbbb
-       l.ori   r5,r0,0xa929            // 0xa929 == l.ori r9
-       l.sh    (TRAMP_SLOT_1+0x0)(r3),r5
-       l.andi  r5,r6,0xffff
-       l.sh    (TRAMP_SLOT_1+0x2)(r3),r5
-
-       /* falthrough, need to set up new jump offset */
-
-
-0:     // l.j
-       l.slli  r6,r4,6                 // original offset shifted left 6 - 2
-//     l.srli  r6,r6,6                 // original offset shifted right 2
-
-       l.slli  r4,r2,4                 // old jump position: EEA shifted left 4
-//     l.srli  r4,r4,6                 // old jump position: shifted right 2
-
-       l.addi  r5,r3,0xc               // new jump position (physical)
-       l.slli  r5,r5,4                 // new jump position: shifted left 4
-
-       // calculate new jump offset
-       // new_off = old_off + (old_jump - new_jump)
-
-       l.sub   r5,r4,r5                // old_jump - new_jump
-       l.add   r5,r6,r5                // orig_off + (old_jump - new_jump)
-       l.srli  r5,r5,6                 // new offset shifted right 2
-
-       // r5 is new jump offset
-                                       // l.j has opcode 0x0...
-       l.sw    TRAMP_SLOT_2(r3),r5     // write it back
-
-       l.j     trampoline_out
-       l.nop
-
-/* ----------------------------- */
-
-3:     // l.jalr
-
-       /* 19 20 aa aa  l.movhi r9,0xaaaa
-        * a9 29 bb bb  l.ori   r9,0xbbbb
-        *
-        * where 0xaaaabbbb is EEA + 0x4 shifted right 2
-        */
-
-       l.addi  r6,r2,0x4               // this is 0xaaaabbbb
-
-                                       // l.movhi r9,0xaaaa
-       l.ori   r5,r0,0x1920            // 0x1920 == l.movhi r9
-       l.sh    (TRAMP_SLOT_0+0x0)(r3),r5
-       l.srli  r5,r6,16
-       l.sh    (TRAMP_SLOT_0+0x2)(r3),r5
-
-                                       // l.ori   r9,0xbbbb
-       l.ori   r5,r0,0xa929            // 0xa929 == l.ori r9
-       l.sh    (TRAMP_SLOT_1+0x0)(r3),r5
-       l.andi  r5,r6,0xffff
-       l.sh    (TRAMP_SLOT_1+0x2)(r3),r5
-
-       l.lhz   r5,(TRAMP_SLOT_2+0x0)(r3)       // load hi part of jump instruction
-       l.andi  r5,r5,0x3ff             // clear out opcode part
-       l.ori   r5,r5,0x4400            // opcode changed from l.jalr -> l.jr
-       l.sh    (TRAMP_SLOT_2+0x0)(r3),r5 // write it back
-
-       /* falthrough */
-
-1:     // l.jr
-       l.j     trampoline_out
-       l.nop
-
-/* ----------------------------- */
-
-4:     // l.bnf
-5:     // l.bf
-       l.slli  r6,r4,6                 // original offset shifted left 6 - 2
-//     l.srli  r6,r6,6                 // original offset shifted right 2
-
-       l.slli  r4,r2,4                 // old jump position: EEA shifted left 4
-//     l.srli  r4,r4,6                 // old jump position: shifted right 2
-
-       l.addi  r5,r3,0xc               // new jump position (physical)
-       l.slli  r5,r5,4                 // new jump position: shifted left 4
-
-       // calculate new jump offset
-       // new_off = old_off + (old_jump - new_jump)
-
-       l.add   r6,r6,r4                // (orig_off + old_jump)
-       l.sub   r6,r6,r5                // (orig_off + old_jump) - new_jump
-       l.srli  r6,r6,6                 // new offset shifted right 2
-
-       // r6 is new jump offset
-       l.lwz   r4,(TRAMP_SLOT_2+0x0)(r3)       // load jump instruction
-       l.srli  r4,r4,16
-       l.andi  r4,r4,0xfc00            // get opcode part
-       l.slli  r4,r4,16
-       l.or    r6,r4,r6                // l.b(n)f new offset
-       l.sw    TRAMP_SLOT_2(r3),r6     // write it back
-
-       /* we need to add l.j to EEA + 0x8 */
-       tophys  (r4,r2)                 // may not be needed (due to shifts down_
-       l.addi  r4,r4,(0x8 - 0x8)       // jump target = r2 + 0x8 (compensate for 0x8)
-                                       // jump position = r5 + 0x8 (0x8 compensated)
-       l.sub   r4,r4,r5                // jump offset = target - new_position + 0x8
-
-       l.slli  r4,r4,4                 // the amount of info in imediate of jump
-       l.srli  r4,r4,6                 // jump instruction with offset
-       l.sw    TRAMP_SLOT_4(r3),r4     // write it to 4th slot
-
-       /* fallthrough */
-
-trampoline_out:
-       // set up new EPC to point to our trampoline code
-       LOAD_SYMBOL_2_GPR(r5,_immu_trampoline)
-       l.mtspr r0,r5,SPR_EPCR_BASE
-
-       // immu_trampoline is (4x) CACHE_LINE aligned
-       // and only 6 instructions long,
-       // so we need to invalidate only 2 lines
-
-       /* Establish cache block size
-          If BS=0, 16;
-          If BS=1, 32;
-          r14 contain block size
-       */
-       l.mfspr r21,r0,SPR_ICCFGR
-       l.andi  r21,r21,SPR_ICCFGR_CBS
-       l.srli  r21,r21,7
-       l.ori   r23,r0,16
-       l.sll   r14,r23,r21
-
-       l.mtspr r0,r5,SPR_ICBIR
-       l.add   r5,r5,r14
-       l.mtspr r0,r5,SPR_ICBIR
-
-       l.jr    r9
-       l.nop
-
-
 /*
- * DSCR: prints a string referenced by r3.
+ * DESC: Prints ASCII character stored in r7
  *
- * PRMS: r3            - address of the first character of null
- *                     terminated string to be printed
+ * PRMS: r7    - a 32-bit value with an ASCII character in the first byte
+ *             position.
  *
- * PREQ: UART at UART_BASE_ADD has to be initialized
+ * PREQ: The UART at UART_BASE_ADD has to be initialized
  *
- * POST: caller should be aware that r3, r9 are changed
+ * POST: internally used but restores:
+ *      r4     - to store UART_BASE_ADD
+ *      r5     - for loading OFF_TXFULL / THRE,TEMT
+ *      r6     - for storing bitmask (SERIAL_8250)
  */
-ENTRY(_emergency_print)
+ENTRY(_emergency_putc)
        EMERGENCY_PRINT_STORE_GPR4
        EMERGENCY_PRINT_STORE_GPR5
        EMERGENCY_PRINT_STORE_GPR6
-       EMERGENCY_PRINT_STORE_GPR7
-2:
-       l.lbz   r7,0(r3)
-       l.sfeq  r7,r0
-       l.bf    9f
-       l.nop
 
-// putc:
        l.movhi r4,hi(UART_BASE_ADD)
+       l.ori   r4,r4,lo(UART_BASE_ADD)
+
+#if defined(CONFIG_SERIAL_LITEUART)
+       /* Check OFF_TXFULL status */
+1:      l.lwz  r5,4(r4)
+       l.andi  r5,r5,0xff
+       l.sfnei r5,0
+       l.bf    1b
+        l.nop
 
+       /* Write character */
+       l.andi  r7,r7,0xff
+       l.sw    0(r4),r7
+#elif defined(CONFIG_SERIAL_8250)
+       /* Check UART LSR THRE (hold) bit */
        l.addi  r6,r0,0x20
 1:      l.lbz   r5,5(r4)
        l.andi  r5,r5,0x20
        l.sfeq  r5,r6
        l.bnf   1b
-       l.nop
+        l.nop
 
+       /* Write character */
        l.sb    0(r4),r7
 
+       /* Check UART LSR THRE|TEMT (hold, empty) bits */
        l.addi  r6,r0,0x60
 1:      l.lbz   r5,5(r4)
        l.andi  r5,r5,0x60
        l.sfeq  r5,r6
        l.bnf   1b
-       l.nop
+        l.nop
+#endif
+       EMERGENCY_PRINT_LOAD_GPR6
+       EMERGENCY_PRINT_LOAD_GPR5
+       EMERGENCY_PRINT_LOAD_GPR4
+       l.jr    r9
+        l.nop
+
+/*
+ * DSCR: prints a string referenced by r3.
+ *
+ * PRMS: r3            - address of the first character of null
+ *                     terminated string to be printed
+ *
+ * PREQ: UART at UART_BASE_ADD has to be initialized
+ *
+ * POST: caller should be aware that r3, r9 are changed
+ */
+ENTRY(_emergency_print)
+       EMERGENCY_PRINT_STORE_GPR7
+       EMERGENCY_PRINT_STORE_GPR9
+
+       /* Load character to r7, check for null terminator */
+2:     l.lbz   r7,0(r3)
+       l.sfeqi r7,0x0
+       l.bf    9f
+        l.nop
+
+       l.jal   _emergency_putc
+        l.nop
 
        /* next character */
        l.j     2b
-       l.addi  r3,r3,0x1
+        l.addi r3,r3,0x1
 
 9:
+       EMERGENCY_PRINT_LOAD_GPR9
        EMERGENCY_PRINT_LOAD_GPR7
-       EMERGENCY_PRINT_LOAD_GPR6
-       EMERGENCY_PRINT_LOAD_GPR5
-       EMERGENCY_PRINT_LOAD_GPR4
        l.jr    r9
-       l.nop
+        l.nop
 
+/*
+ * DSCR: prints a number in r3 in hex.
+ *
+ * PRMS: r3            - a 32-bit unsigned integer
+ *
+ * PREQ: UART at UART_BASE_ADD has to be initialized
+ *
+ * POST: caller should be aware that r3, r9 are changed
+ */
 ENTRY(_emergency_print_nr)
-       EMERGENCY_PRINT_STORE_GPR4
-       EMERGENCY_PRINT_STORE_GPR5
-       EMERGENCY_PRINT_STORE_GPR6
        EMERGENCY_PRINT_STORE_GPR7
        EMERGENCY_PRINT_STORE_GPR8
+       EMERGENCY_PRINT_STORE_GPR9
 
        l.addi  r8,r0,32                // shift register
 
@@ -1609,58 +1449,39 @@ ENTRY(_emergency_print_nr)
        /* don't skip the last zero if number == 0x0 */
        l.sfeqi r8,0x4
        l.bf    2f
-       l.nop
+        l.nop
 
        l.sfeq  r7,r0
        l.bf    1b
-       l.nop
+        l.nop
 
 2:
        l.srl   r7,r3,r8
 
        l.andi  r7,r7,0xf
        l.sflts r8,r0
-       l.bf    9f
+        l.bf   9f
 
+       /* Numbers greater than 9 translate to a-f */
        l.sfgtui r7,0x9
        l.bnf   8f
-       l.nop
+        l.nop
        l.addi  r7,r7,0x27
 
-8:
-       l.addi  r7,r7,0x30
-// putc:
-       l.movhi r4,hi(UART_BASE_ADD)
-
-       l.addi  r6,r0,0x20
-1:      l.lbz   r5,5(r4)
-       l.andi  r5,r5,0x20
-       l.sfeq  r5,r6
-       l.bnf   1b
-       l.nop
-
-       l.sb    0(r4),r7
-
-       l.addi  r6,r0,0x60
-1:      l.lbz   r5,5(r4)
-       l.andi  r5,r5,0x60
-       l.sfeq  r5,r6
-       l.bnf   1b
-       l.nop
+       /* Convert to ascii and output character */
+8:     l.jal   _emergency_putc
+        l.addi r7,r7,0x30
 
        /* next character */
        l.j     2b
        l.addi  r8,r8,-0x4
 
 9:
+       EMERGENCY_PRINT_LOAD_GPR9
        EMERGENCY_PRINT_LOAD_GPR8
        EMERGENCY_PRINT_LOAD_GPR7
-       EMERGENCY_PRINT_LOAD_GPR6
-       EMERGENCY_PRINT_LOAD_GPR5
-       EMERGENCY_PRINT_LOAD_GPR4
        l.jr    r9
-       l.nop
-
+        l.nop
 
 /*
  * This should be used for debugging only.
@@ -1685,7 +1506,9 @@ ENTRY(_emergency_print_nr)
 
 ENTRY(_early_uart_init)
        l.movhi r3,hi(UART_BASE_ADD)
+       l.ori   r3,r3,lo(UART_BASE_ADD)
 
+#if defined(CONFIG_SERIAL_8250)
        l.addi  r4,r0,0x7
        l.sb    0x2(r3),r4
 
@@ -1703,9 +1526,10 @@ ENTRY(_early_uart_init)
        l.addi  r4,r0,((UART_DIVISOR) & 0x000000ff)
        l.sb    UART_DLL(r3),r4
        l.sb    0x3(r3),r5
+#endif
 
        l.jr    r9
-       l.nop
+        l.nop
 
        .align  0x1000
        .global _secondary_evbar
@@ -1720,13 +1544,13 @@ _secondary_evbar:
 
        .section .rodata
 _string_unhandled_exception:
-       .string "\n\rRunarunaround: Unhandled exception 0x\0"
+       .string "\r\nRunarunaround: Unhandled exception 0x\0"
 
 _string_epc_prefix:
        .string ": EPC=0x\0"
 
 _string_nl:
-       .string "\n\r\0"
+       .string "\r\n\0"
 
 
 /* ========================================[ page aligned structures ]=== */