hc
2024-05-10 cde9070d9970eef1f7ec2360586c802a16230ad8
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
 * Copyright (C) 2008 Freescale Semiconductor, Inc. All rights reserved.
 * Dave Liu <daveliu@freescale.com>
 * copy from idle_6xx.S and modify for e500 based processor,
 * implement the power_save function in idle.
 */
 
#include <linux/threads.h>
#include <asm/reg.h>
#include <asm/page.h>
#include <asm/cputable.h>
#include <asm/thread_info.h>
#include <asm/ppc_asm.h>
#include <asm/asm-offsets.h>
#include <asm/feature-fixups.h>
 
   .text
 
_GLOBAL(e500_idle)
   lwz    r4,TI_LOCAL_FLAGS(r2)    /* set napping bit */
   ori    r4,r4,_TLF_NAPPING    /* so when we take an exception */
   stw    r4,TI_LOCAL_FLAGS(r2)    /* it will return to our caller */
 
#ifdef CONFIG_PPC_E500MC
   wrteei    1
1:    wait
 
   /*
    * Guard against spurious wakeups (e.g. from a hypervisor) --
    * any real interrupt will cause us to return to LR due to
    * _TLF_NAPPING.
    */
   b    1b
#else
   /* Check if we can nap or doze, put HID0 mask in r3 */
   lis    r3,0
BEGIN_FTR_SECTION
   lis    r3,HID0_DOZE@h
END_FTR_SECTION_IFSET(CPU_FTR_CAN_DOZE)
 
BEGIN_FTR_SECTION
   /* Now check if user enabled NAP mode */
   lis    r4,powersave_nap@ha
   lwz    r4,powersave_nap@l(r4)
   cmpwi    0,r4,0
   beq    1f
   stwu    r1,-16(r1)
   mflr    r0
   stw    r0,20(r1)
   bl    flush_dcache_L1
   lwz    r0,20(r1)
   addi    r1,r1,16
   mtlr    r0
   lis    r3,HID0_NAP@h
END_FTR_SECTION_IFSET(CPU_FTR_CAN_NAP)
1:
   /* Go to NAP or DOZE now */
   mfspr    r4,SPRN_HID0
   rlwinm    r4,r4,0,~(HID0_DOZE|HID0_NAP|HID0_SLEEP)
   or    r4,r4,r3
   isync
   mtspr    SPRN_HID0,r4
   isync
 
   mfmsr    r7
   oris    r7,r7,MSR_WE@h
   ori    r7,r7,MSR_EE
   msync
   mtmsr    r7
   isync
2:    b    2b
#endif /* !E500MC */
 
/*
 * Return from NAP/DOZE mode, restore some CPU specific registers,
 * r2 containing physical address of current.
 * r11 points to the exception frame (physical address).
 * We have to preserve r10.
 */
_GLOBAL(power_save_ppc32_restore)
   lwz    r9,_LINK(r11)        /* interrupted in e500_idle */
   stw    r9,_NIP(r11)        /* make it do a blr */
 
#ifdef CONFIG_SMP
   lwz    r11,TASK_CPU(r2)        /* get cpu number * 4 */
   slwi    r11,r11,2
#else
   li    r11,0
#endif
 
   b    transfer_to_handler_cont
_ASM_NOKPROBE_SYMBOL(power_save_ppc32_restore)