| 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
| 2 | /* Copyright (C) 2017 Andes Technology Corporation */ |
| 3 | |
| 4 | #include <asm/memory.h> |
| 5 | |
| 6 | .data |
| 7 | .global sp_tmp |
| 8 | sp_tmp: |
| 9 | .long |
| 10 | |
| 11 | .text |
| 12 | .globl suspend2ram |
| 13 | .globl cpu_resume |
| 14 | |
| 15 | suspend2ram: |
| 16 | pushm $r0, $r31 |
| 17 | #if defined(CONFIG_HWZOL) |
| 18 | mfusr $r0, $lc |
| 19 | mfusr $r1, $le |
| 20 | mfusr $r2, $lb |
| 21 | #endif |
| 22 | mfsr $r3, $mr0 |
| 23 | mfsr $r4, $mr1 |
| 24 | mfsr $r5, $mr4 |
| 25 | mfsr $r6, $mr6 |
| 26 | mfsr $r7, $mr7 |
| 27 | mfsr $r8, $mr8 |
| 28 | mfsr $r9, $ir0 |
| 29 | mfsr $r10, $ir1 |
| 30 | mfsr $r11, $ir2 |
| 31 | mfsr $r12, $ir3 |
| 32 | mfsr $r13, $ir9 |
| 33 | mfsr $r14, $ir10 |
| 34 | mfsr $r15, $ir12 |
| 35 | mfsr $r16, $ir13 |
| 36 | mfsr $r17, $ir14 |
| 37 | mfsr $r18, $ir15 |
| 38 | pushm $r0, $r19 |
| 39 | #if defined(CONFIG_FPU) |
| 40 | jal store_fpu_for_suspend |
| 41 | #endif |
| 42 | tlbop FlushAll |
| 43 | isb |
| 44 | |
| 45 | // transfer $sp from va to pa |
| 46 | sethi $r0, hi20(PAGE_OFFSET) |
| 47 | ori $r0, $r0, lo12(PAGE_OFFSET) |
| 48 | movi $r2, PHYS_OFFSET |
| 49 | sub $r1, $sp, $r0 |
| 50 | add $r2, $r1, $r2 |
| 51 | |
| 52 | // store pa($sp) to sp_tmp |
| 53 | sethi $r1, hi20(sp_tmp) |
| 54 | swi $r2, [$r1 + lo12(sp_tmp)] |
| 55 | |
| 56 | pushm $r16, $r25 |
| 57 | pushm $r29, $r30 |
| 58 | #ifdef CONFIG_CACHE_L2 |
| 59 | jal dcache_wb_all_level |
| 60 | #else |
| 61 | jal cpu_dcache_wb_all |
| 62 | #endif |
| 63 | popm $r29, $r30 |
| 64 | popm $r16, $r25 |
| 65 | |
| 66 | // get wake_mask and loop in standby |
| 67 | la $r1, wake_mask |
| 68 | lwi $r1, [$r1] |
| 69 | self_loop: |
| 70 | standby wake_grant |
| 71 | mfsr $r2, $ir15 |
| 72 | and $r2, $r1, $r2 |
| 73 | beqz $r2, self_loop |
| 74 | |
| 75 | // set ipc to resume address |
| 76 | la $r1, resume_addr |
| 77 | lwi $r1, [$r1] |
| 78 | mtsr $r1, $ipc |
| 79 | isb |
| 80 | |
| 81 | // reset psw, turn off the address translation |
| 82 | li $r2, 0x7000a |
| 83 | mtsr $r2, $ipsw |
| 84 | isb |
| 85 | |
| 86 | iret |
| 87 | cpu_resume: |
| 88 | // translate the address of sp_tmp variable to pa |
| 89 | la $r1, sp_tmp |
| 90 | sethi $r0, hi20(PAGE_OFFSET) |
| 91 | ori $r0, $r0, lo12(PAGE_OFFSET) |
| 92 | movi $r2, PHYS_OFFSET |
| 93 | sub $r1, $r1, $r0 |
| 94 | add $r1, $r1, $r2 |
| 95 | |
| 96 | // access the sp_tmp to get stack pointer |
| 97 | lwi $sp, [$r1] |
| 98 | |
| 99 | popm $r0, $r19 |
| 100 | #if defined(CONFIG_HWZOL) |
| 101 | mtusr $r0, $lb |
| 102 | mtusr $r1, $lc |
| 103 | mtusr $r2, $le |
| 104 | #endif |
| 105 | mtsr $r3, $mr0 |
| 106 | mtsr $r4, $mr1 |
| 107 | mtsr $r5, $mr4 |
| 108 | mtsr $r6, $mr6 |
| 109 | mtsr $r7, $mr7 |
| 110 | mtsr $r8, $mr8 |
| 111 | // set original psw to ipsw |
| 112 | mtsr $r9, $ir1 |
| 113 | |
| 114 | mtsr $r11, $ir2 |
| 115 | mtsr $r12, $ir3 |
| 116 | |
| 117 | // set ipc to RR |
| 118 | la $r13, RR |
| 119 | mtsr $r13, $ir9 |
| 120 | |
| 121 | mtsr $r14, $ir10 |
| 122 | mtsr $r15, $ir12 |
| 123 | mtsr $r16, $ir13 |
| 124 | mtsr $r17, $ir14 |
| 125 | mtsr $r18, $ir15 |
| 126 | popm $r0, $r31 |
| 127 | |
| 128 | isb |
| 129 | iret |
| 130 | RR: |
| 131 | ret |