suspend-asm.S (10815B)
1/* SPDX-License-Identifier: GPL-2.0-only */ 2/* 3 * Enter and leave deep sleep state on MPC83xx 4 * 5 * Copyright (c) 2006-2008 Freescale Semiconductor, Inc. 6 * Author: Scott Wood <scottwood@freescale.com> 7 */ 8 9#include <asm/page.h> 10#include <asm/ppc_asm.h> 11#include <asm/reg.h> 12#include <asm/asm-offsets.h> 13 14#define SS_MEMSAVE 0x00 /* First 8 bytes of RAM */ 15#define SS_HID 0x08 /* 3 HIDs */ 16#define SS_IABR 0x14 /* 2 IABRs */ 17#define SS_IBCR 0x1c 18#define SS_DABR 0x20 /* 2 DABRs */ 19#define SS_DBCR 0x28 20#define SS_SP 0x2c 21#define SS_SR 0x30 /* 16 segment registers */ 22#define SS_R2 0x70 23#define SS_MSR 0x74 24#define SS_SDR1 0x78 25#define SS_LR 0x7c 26#define SS_SPRG 0x80 /* 8 SPRGs */ 27#define SS_DBAT 0xa0 /* 8 DBATs */ 28#define SS_IBAT 0xe0 /* 8 IBATs */ 29#define SS_TB 0x120 30#define SS_CR 0x128 31#define SS_GPREG 0x12c /* r12-r31 */ 32#define STATE_SAVE_SIZE 0x17c 33 34 .section .data 35 .align 5 36 37mpc83xx_sleep_save_area: 38 .space STATE_SAVE_SIZE 39immrbase: 40 .long 0 41 42 .section .text 43 .align 5 44 45 /* r3 = physical address of IMMR */ 46_GLOBAL(mpc83xx_enter_deep_sleep) 47 lis r4, immrbase@ha 48 stw r3, immrbase@l(r4) 49 50 /* The first 2 words of memory are used to communicate with the 51 * bootloader, to tell it how to resume. 52 * 53 * The first word is the magic number 0xf5153ae5, and the second 54 * is the pointer to mpc83xx_deep_resume. 55 * 56 * The original content of these two words is saved in SS_MEMSAVE. 57 */ 58 59 lis r3, mpc83xx_sleep_save_area@h 60 ori r3, r3, mpc83xx_sleep_save_area@l 61 62 lis r4, KERNELBASE@h 63 lwz r5, 0(r4) 64 lwz r6, 4(r4) 65 66 stw r5, SS_MEMSAVE+0(r3) 67 stw r6, SS_MEMSAVE+4(r3) 68 69 mfspr r5, SPRN_HID0 70 mfspr r6, SPRN_HID1 71 mfspr r7, SPRN_HID2 72 73 stw r5, SS_HID+0(r3) 74 stw r6, SS_HID+4(r3) 75 stw r7, SS_HID+8(r3) 76 77 mfspr r4, SPRN_IABR 78 mfspr r5, SPRN_IABR2 79 mfspr r6, SPRN_IBCR 80 mfspr r7, SPRN_DABR 81 mfspr r8, SPRN_DABR2 82 mfspr r9, SPRN_DBCR 83 84 stw r4, SS_IABR+0(r3) 85 stw r5, SS_IABR+4(r3) 86 stw r6, SS_IBCR(r3) 87 stw r7, SS_DABR+0(r3) 88 stw r8, SS_DABR+4(r3) 89 stw r9, SS_DBCR(r3) 90 91 mfspr r4, SPRN_SPRG0 92 mfspr r5, SPRN_SPRG1 93 mfspr r6, SPRN_SPRG2 94 mfspr r7, SPRN_SPRG3 95 mfsdr1 r8 96 97 stw r4, SS_SPRG+0(r3) 98 stw r5, SS_SPRG+4(r3) 99 stw r6, SS_SPRG+8(r3) 100 stw r7, SS_SPRG+12(r3) 101 stw r8, SS_SDR1(r3) 102 103 mfspr r4, SPRN_SPRG4 104 mfspr r5, SPRN_SPRG5 105 mfspr r6, SPRN_SPRG6 106 mfspr r7, SPRN_SPRG7 107 108 stw r4, SS_SPRG+16(r3) 109 stw r5, SS_SPRG+20(r3) 110 stw r6, SS_SPRG+24(r3) 111 stw r7, SS_SPRG+28(r3) 112 113 mfspr r4, SPRN_DBAT0U 114 mfspr r5, SPRN_DBAT0L 115 mfspr r6, SPRN_DBAT1U 116 mfspr r7, SPRN_DBAT1L 117 118 stw r4, SS_DBAT+0x00(r3) 119 stw r5, SS_DBAT+0x04(r3) 120 stw r6, SS_DBAT+0x08(r3) 121 stw r7, SS_DBAT+0x0c(r3) 122 123 mfspr r4, SPRN_DBAT2U 124 mfspr r5, SPRN_DBAT2L 125 mfspr r6, SPRN_DBAT3U 126 mfspr r7, SPRN_DBAT3L 127 128 stw r4, SS_DBAT+0x10(r3) 129 stw r5, SS_DBAT+0x14(r3) 130 stw r6, SS_DBAT+0x18(r3) 131 stw r7, SS_DBAT+0x1c(r3) 132 133 mfspr r4, SPRN_DBAT4U 134 mfspr r5, SPRN_DBAT4L 135 mfspr r6, SPRN_DBAT5U 136 mfspr r7, SPRN_DBAT5L 137 138 stw r4, SS_DBAT+0x20(r3) 139 stw r5, SS_DBAT+0x24(r3) 140 stw r6, SS_DBAT+0x28(r3) 141 stw r7, SS_DBAT+0x2c(r3) 142 143 mfspr r4, SPRN_DBAT6U 144 mfspr r5, SPRN_DBAT6L 145 mfspr r6, SPRN_DBAT7U 146 mfspr r7, SPRN_DBAT7L 147 148 stw r4, SS_DBAT+0x30(r3) 149 stw r5, SS_DBAT+0x34(r3) 150 stw r6, SS_DBAT+0x38(r3) 151 stw r7, SS_DBAT+0x3c(r3) 152 153 mfspr r4, SPRN_IBAT0U 154 mfspr r5, SPRN_IBAT0L 155 mfspr r6, SPRN_IBAT1U 156 mfspr r7, SPRN_IBAT1L 157 158 stw r4, SS_IBAT+0x00(r3) 159 stw r5, SS_IBAT+0x04(r3) 160 stw r6, SS_IBAT+0x08(r3) 161 stw r7, SS_IBAT+0x0c(r3) 162 163 mfspr r4, SPRN_IBAT2U 164 mfspr r5, SPRN_IBAT2L 165 mfspr r6, SPRN_IBAT3U 166 mfspr r7, SPRN_IBAT3L 167 168 stw r4, SS_IBAT+0x10(r3) 169 stw r5, SS_IBAT+0x14(r3) 170 stw r6, SS_IBAT+0x18(r3) 171 stw r7, SS_IBAT+0x1c(r3) 172 173 mfspr r4, SPRN_IBAT4U 174 mfspr r5, SPRN_IBAT4L 175 mfspr r6, SPRN_IBAT5U 176 mfspr r7, SPRN_IBAT5L 177 178 stw r4, SS_IBAT+0x20(r3) 179 stw r5, SS_IBAT+0x24(r3) 180 stw r6, SS_IBAT+0x28(r3) 181 stw r7, SS_IBAT+0x2c(r3) 182 183 mfspr r4, SPRN_IBAT6U 184 mfspr r5, SPRN_IBAT6L 185 mfspr r6, SPRN_IBAT7U 186 mfspr r7, SPRN_IBAT7L 187 188 stw r4, SS_IBAT+0x30(r3) 189 stw r5, SS_IBAT+0x34(r3) 190 stw r6, SS_IBAT+0x38(r3) 191 stw r7, SS_IBAT+0x3c(r3) 192 193 mfmsr r4 194 mflr r5 195 mfcr r6 196 197 stw r4, SS_MSR(r3) 198 stw r5, SS_LR(r3) 199 stw r6, SS_CR(r3) 200 stw r1, SS_SP(r3) 201 stw r2, SS_R2(r3) 202 2031: mftbu r4 204 mftb r5 205 mftbu r6 206 cmpw r4, r6 207 bne 1b 208 209 stw r4, SS_TB+0(r3) 210 stw r5, SS_TB+4(r3) 211 212 stmw r12, SS_GPREG(r3) 213 214 li r4, 0 215 addi r6, r3, SS_SR-4 2161: mfsrin r5, r4 217 stwu r5, 4(r6) 218 addis r4, r4, 0x1000 219 cmpwi r4, 0 220 bne 1b 221 222 /* Disable machine checks and critical exceptions */ 223 mfmsr r4 224 rlwinm r4, r4, 0, ~MSR_CE 225 rlwinm r4, r4, 0, ~MSR_ME 226 mtmsr r4 227 isync 228 229#define TMP_VIRT_IMMR 0xf0000000 230#define DEFAULT_IMMR_VALUE 0xff400000 231#define IMMRBAR_BASE 0x0000 232 233 lis r4, immrbase@ha 234 lwz r4, immrbase@l(r4) 235 236 /* Use DBAT0 to address the current IMMR space */ 237 238 ori r4, r4, 0x002a 239 mtspr SPRN_DBAT0L, r4 240 lis r8, TMP_VIRT_IMMR@h 241 ori r4, r8, 0x001e /* 1 MByte accessible from Kernel Space only */ 242 mtspr SPRN_DBAT0U, r4 243 isync 244 245 /* Use DBAT1 to address the original IMMR space */ 246 247 lis r4, DEFAULT_IMMR_VALUE@h 248 ori r4, r4, 0x002a 249 mtspr SPRN_DBAT1L, r4 250 lis r9, (TMP_VIRT_IMMR + 0x01000000)@h 251 ori r4, r9, 0x001e /* 1 MByte accessible from Kernel Space only */ 252 mtspr SPRN_DBAT1U, r4 253 isync 254 255 /* Use DBAT2 to address the beginning of RAM. This isn't done 256 * using the normal virtual mapping, because with page debugging 257 * enabled it will be read-only. 258 */ 259 260 li r4, 0x0002 261 mtspr SPRN_DBAT2L, r4 262 lis r4, KERNELBASE@h 263 ori r4, r4, 0x001e /* 1 MByte accessible from Kernel Space only */ 264 mtspr SPRN_DBAT2U, r4 265 isync 266 267 /* Flush the cache with our BAT, as there will be TLB misses 268 * otherwise if page debugging is enabled, and these misses 269 * will disturb the PLRU algorithm. 270 */ 271 272 bl __flush_disable_L1 273 274 /* Keep the i-cache enabled, so the hack below for low-boot 275 * flash will work. 276 */ 277 mfspr r3, SPRN_HID0 278 ori r3, r3, HID0_ICE 279 mtspr SPRN_HID0, r3 280 isync 281 282 lis r6, 0xf515 283 ori r6, r6, 0x3ae5 284 285 lis r7, mpc83xx_deep_resume@h 286 ori r7, r7, mpc83xx_deep_resume@l 287 tophys(r7, r7) 288 289 lis r5, KERNELBASE@h 290 stw r6, 0(r5) 291 stw r7, 4(r5) 292 293 /* Reset BARs */ 294 295 li r4, 0 296 stw r4, 0x0024(r8) 297 stw r4, 0x002c(r8) 298 stw r4, 0x0034(r8) 299 stw r4, 0x003c(r8) 300 stw r4, 0x0064(r8) 301 stw r4, 0x006c(r8) 302 303 /* Rev 1 of the 8313 has problems with wakeup events that are 304 * pending during the transition to deep sleep state (such as if 305 * the PCI host sets the state to D3 and then D0 in rapid 306 * succession). This check shrinks the race window somewhat. 307 * 308 * See erratum PCI23, though the problem is not limited 309 * to PCI. 310 */ 311 312 lwz r3, 0x0b04(r8) 313 andi. r3, r3, 1 314 bne- mpc83xx_deep_resume 315 316 /* Move IMMR back to the default location, following the 317 * procedure specified in the MPC8313 manual. 318 */ 319 lwz r4, IMMRBAR_BASE(r8) 320 isync 321 lis r4, DEFAULT_IMMR_VALUE@h 322 stw r4, IMMRBAR_BASE(r8) 323 lis r4, KERNELBASE@h 324 lwz r4, 0(r4) 325 isync 326 lwz r4, IMMRBAR_BASE(r9) 327 mr r8, r9 328 isync 329 330 /* Check the Reset Configuration Word to see whether flash needs 331 * to be mapped at a low address or a high address. 332 */ 333 334 lwz r4, 0x0904(r8) 335 andis. r4, r4, 0x0400 336 li r4, 0 337 beq boot_low 338 lis r4, 0xff80 339boot_low: 340 stw r4, 0x0020(r8) 341 lis r7, 0x8000 342 ori r7, r7, 0x0016 343 344 mfspr r5, SPRN_HID0 345 rlwinm r5, r5, 0, ~(HID0_DOZE | HID0_NAP) 346 oris r5, r5, HID0_SLEEP@h 347 mtspr SPRN_HID0, r5 348 isync 349 350 mfmsr r5 351 oris r5, r5, MSR_POW@h 352 353 /* Enable the flash mapping at the appropriate address. This 354 * mapping will override the RAM mapping if booting low, so there's 355 * no need to disable the latter. This must be done inside the same 356 * cache line as setting MSR_POW, so that no instruction fetches 357 * from RAM happen after the flash mapping is turned on. 358 */ 359 360 .align 5 361 stw r7, 0x0024(r8) 362 sync 363 isync 364 mtmsr r5 365 isync 3661: b 1b 367 368mpc83xx_deep_resume: 369 lis r4, 1f@h 370 ori r4, r4, 1f@l 371 tophys(r4, r4) 372 mtsrr0 r4 373 374 mfmsr r4 375 rlwinm r4, r4, 0, ~(MSR_IR | MSR_DR) 376 mtsrr1 r4 377 378 rfi 379 3801: tlbia 381 bl __inval_enable_L1 382 383 lis r3, mpc83xx_sleep_save_area@h 384 ori r3, r3, mpc83xx_sleep_save_area@l 385 tophys(r3, r3) 386 387 lwz r5, SS_MEMSAVE+0(r3) 388 lwz r6, SS_MEMSAVE+4(r3) 389 390 stw r5, 0(0) 391 stw r6, 4(0) 392 393 lwz r5, SS_HID+0(r3) 394 lwz r6, SS_HID+4(r3) 395 lwz r7, SS_HID+8(r3) 396 397 mtspr SPRN_HID0, r5 398 mtspr SPRN_HID1, r6 399 mtspr SPRN_HID2, r7 400 401 lwz r4, SS_IABR+0(r3) 402 lwz r5, SS_IABR+4(r3) 403 lwz r6, SS_IBCR(r3) 404 lwz r7, SS_DABR+0(r3) 405 lwz r8, SS_DABR+4(r3) 406 lwz r9, SS_DBCR(r3) 407 408 mtspr SPRN_IABR, r4 409 mtspr SPRN_IABR2, r5 410 mtspr SPRN_IBCR, r6 411 mtspr SPRN_DABR, r7 412 mtspr SPRN_DABR2, r8 413 mtspr SPRN_DBCR, r9 414 415 li r4, 0 416 addi r6, r3, SS_SR-4 4171: lwzu r5, 4(r6) 418 mtsrin r5, r4 419 addis r4, r4, 0x1000 420 cmpwi r4, 0 421 bne 1b 422 423 lwz r4, SS_DBAT+0x00(r3) 424 lwz r5, SS_DBAT+0x04(r3) 425 lwz r6, SS_DBAT+0x08(r3) 426 lwz r7, SS_DBAT+0x0c(r3) 427 428 mtspr SPRN_DBAT0U, r4 429 mtspr SPRN_DBAT0L, r5 430 mtspr SPRN_DBAT1U, r6 431 mtspr SPRN_DBAT1L, r7 432 433 lwz r4, SS_DBAT+0x10(r3) 434 lwz r5, SS_DBAT+0x14(r3) 435 lwz r6, SS_DBAT+0x18(r3) 436 lwz r7, SS_DBAT+0x1c(r3) 437 438 mtspr SPRN_DBAT2U, r4 439 mtspr SPRN_DBAT2L, r5 440 mtspr SPRN_DBAT3U, r6 441 mtspr SPRN_DBAT3L, r7 442 443 lwz r4, SS_DBAT+0x20(r3) 444 lwz r5, SS_DBAT+0x24(r3) 445 lwz r6, SS_DBAT+0x28(r3) 446 lwz r7, SS_DBAT+0x2c(r3) 447 448 mtspr SPRN_DBAT4U, r4 449 mtspr SPRN_DBAT4L, r5 450 mtspr SPRN_DBAT5U, r6 451 mtspr SPRN_DBAT5L, r7 452 453 lwz r4, SS_DBAT+0x30(r3) 454 lwz r5, SS_DBAT+0x34(r3) 455 lwz r6, SS_DBAT+0x38(r3) 456 lwz r7, SS_DBAT+0x3c(r3) 457 458 mtspr SPRN_DBAT6U, r4 459 mtspr SPRN_DBAT6L, r5 460 mtspr SPRN_DBAT7U, r6 461 mtspr SPRN_DBAT7L, r7 462 463 lwz r4, SS_IBAT+0x00(r3) 464 lwz r5, SS_IBAT+0x04(r3) 465 lwz r6, SS_IBAT+0x08(r3) 466 lwz r7, SS_IBAT+0x0c(r3) 467 468 mtspr SPRN_IBAT0U, r4 469 mtspr SPRN_IBAT0L, r5 470 mtspr SPRN_IBAT1U, r6 471 mtspr SPRN_IBAT1L, r7 472 473 lwz r4, SS_IBAT+0x10(r3) 474 lwz r5, SS_IBAT+0x14(r3) 475 lwz r6, SS_IBAT+0x18(r3) 476 lwz r7, SS_IBAT+0x1c(r3) 477 478 mtspr SPRN_IBAT2U, r4 479 mtspr SPRN_IBAT2L, r5 480 mtspr SPRN_IBAT3U, r6 481 mtspr SPRN_IBAT3L, r7 482 483 lwz r4, SS_IBAT+0x20(r3) 484 lwz r5, SS_IBAT+0x24(r3) 485 lwz r6, SS_IBAT+0x28(r3) 486 lwz r7, SS_IBAT+0x2c(r3) 487 488 mtspr SPRN_IBAT4U, r4 489 mtspr SPRN_IBAT4L, r5 490 mtspr SPRN_IBAT5U, r6 491 mtspr SPRN_IBAT5L, r7 492 493 lwz r4, SS_IBAT+0x30(r3) 494 lwz r5, SS_IBAT+0x34(r3) 495 lwz r6, SS_IBAT+0x38(r3) 496 lwz r7, SS_IBAT+0x3c(r3) 497 498 mtspr SPRN_IBAT6U, r4 499 mtspr SPRN_IBAT6L, r5 500 mtspr SPRN_IBAT7U, r6 501 mtspr SPRN_IBAT7L, r7 502 503 lwz r4, SS_SPRG+16(r3) 504 lwz r5, SS_SPRG+20(r3) 505 lwz r6, SS_SPRG+24(r3) 506 lwz r7, SS_SPRG+28(r3) 507 508 mtspr SPRN_SPRG4, r4 509 mtspr SPRN_SPRG5, r5 510 mtspr SPRN_SPRG6, r6 511 mtspr SPRN_SPRG7, r7 512 513 lwz r4, SS_SPRG+0(r3) 514 lwz r5, SS_SPRG+4(r3) 515 lwz r6, SS_SPRG+8(r3) 516 lwz r7, SS_SPRG+12(r3) 517 lwz r8, SS_SDR1(r3) 518 519 mtspr SPRN_SPRG0, r4 520 mtspr SPRN_SPRG1, r5 521 mtspr SPRN_SPRG2, r6 522 mtspr SPRN_SPRG3, r7 523 mtsdr1 r8 524 525 lwz r4, SS_MSR(r3) 526 lwz r5, SS_LR(r3) 527 lwz r6, SS_CR(r3) 528 lwz r1, SS_SP(r3) 529 lwz r2, SS_R2(r3) 530 531 mtsrr1 r4 532 mtsrr0 r5 533 mtcr r6 534 535 li r4, 0 536 mtspr SPRN_TBWL, r4 537 538 lwz r4, SS_TB+0(r3) 539 lwz r5, SS_TB+4(r3) 540 541 mtspr SPRN_TBWU, r4 542 mtspr SPRN_TBWL, r5 543 544 lmw r12, SS_GPREG(r3) 545 546 /* Kick decrementer */ 547 li r0, 1 548 mtdec r0 549 550 rfi 551_ASM_NOKPROBE_SYMBOL(mpc83xx_deep_resume)