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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
|
// $Id: gpe_control.pS,v 1.1.1.1 2013/12/11 20:49:20 bcbrock Exp $
// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/gpe_control.pS,v $
//-----------------------------------------------------------------------------
// *! (C) Copyright International Business Machines Corp. 2013
// *! All Rights Reserved -- Property of IBM
// *! *** IBM Confidential ***
//-----------------------------------------------------------------------------
/// \file gpe_control.S
/// \brief GPE procedures for control
.nolist
#include "ssx.h"
#include "pgas.h"
#include "gpe.h"
#include "gpe_control.h"
.list
.oci
.text.pore
/// \fn gpe_set_pstates(GpeSetPstatesParms *parms)
/// \brief Set core chiplet Pstate registers
///
/// This routine loops through an array of PcbsPstateRegs structures
/// holding the register images to be actuated. A pointer to the array is
/// provided as the \a registers parameter. For every core chiplet
/// appearing in the \a cfg parameter, those registers marked in the \a select
/// parameter are updated.
///
/// When the PMBR is being updated, an option is provided to
/// set PCBS_PCBSPM_MODE_REG[enable_pmax_sync_interrupt] around the
/// update of PMBR. This will cause a SYNC interrupt from each
/// core. This mode currently does not set up the sync protocol in the PMC -
/// the caller must do that.
///
/// Note that actuating the PMCR and PMICR using this method requires that the
/// PCB Slave bit PMGP0_REG.pm_spr_override_en is set.
#ifdef DOXYGEN_ONLY
void gpe_set_pstates(GpeSetPstatesParms *parms);
#endif
/// \cond
// Register usage:
//
// A1 : Holds the (constant) pointer to the paramaters
// A0 : Holds the (varying) pointer to the next register block
// D1 : Holds the (varying) ChipConfig mask
// D0 : Scratch
// P0 : Holds the (varying) chiplet id
.global gpe_set_pstates
gpe_set_pstates:
// Set up registers. The chiplet part of the ChipConfig is left
// justified in D1, which will be rotated on each loop.
mr A1, ETR
ld D0, GPESETPSTATESPARMS_REGS, A1
mr A0, D0
ld D0, GPESETPSTATESPARMS_CONFIG, A1
mr D1, D0
left_justify_core_config D1
lpcs P0, 0x10000000 # Load P0 with core chiplet 0 address
ls CTR, PGP_NCORES
bra start_loop
set_pstates_loop:
// If the chiplet is not configured, simply continue
andi D0, D1, 0x8000000000000000
braz D0, set_pstates_continue
// Test/actuate each register in order
ldandi D0, GPESETPSTATESPARMS_SELECT, A1, GPE_SET_PSTATES_PMBR
braz D0, pmicr
// PMBR.
// If SYNCing, the register write is wrapped by a read-modify-write of
// the PCBS_PCBSPM_MODE_REG which enables the PMAX Sync
// acknowledge. Note that the original PCBSPM mode reg is saved and
// restored.
pmbr:
ldandi D0, GPESETPSTATESPARMS_SELECT, A1, GPE_SET_PSTATES_SYNC
braz D0, nosync
sync:
ld D0, PCBS_PCBSPM_MODE_REG, P0
la A1, gsp_pcbs_pcbspm_mode_reg
std D0, 0, A1
ori D0, D0, PCBS_PCBSPM_MODE_REG_ENABLE_PMC_PMAX_SYNC_NOTIFICATION
std D0, PCBS_PCBSPM_MODE_REG, P0
ld D0, PCBSPSTATEREGS_PMBR, A0
std D0, PCBS_POWER_MANAGEMENT_BOUNDS_REG, P0
ld D0, 0, A1
std D0, PCBS_PCBSPM_MODE_REG, P0
// restore A1
mr A1, ETR
bra pmicr
nosync:
ld D0, PCBSPSTATEREGS_PMBR, A0
std D0, PCBS_POWER_MANAGEMENT_BOUNDS_REG, P0
// PMICR
pmicr:
ldandi D0, GPESETPSTATESPARMS_SELECT, A1, GPE_SET_PSTATES_PMICR
braz D0, pmcr
ld D0, PCBSPSTATEREGS_PMICR, A0
std D0, PCBS_POWER_MANAGEMENT_IDLE_CONTROL_REG, P0
// PMCR
pmcr:
ldandi D0, GPESETPSTATESPARMS_SELECT, A1, GPE_SET_PSTATES_PMCR
braz D0, set_pstates_continue
ld D0, PCBSPSTATEREGS_PMCR, A0
std D0, PCBS_POWER_MANAGEMENT_CONTROL_REG, P0
set_pstates_continue:
// Increment the chiplet index and data pointer, then loop or halt.
adds P0, P0, 1
adds A0, A0, SIZEOF_PCBSPSTATEREGS
rotldi D1, D1, 1
start_loop:
loop set_pstates_loop
halt
.epilogue gpe_set_pstates
/// \endcond
/// Data storage for procedures.
/// Placing data in the .rodata section to prevent the 405 from stomping them.
.section .rodata
.balign 8
/// data for gpe_set_pstates
/// \cond
gsp_pcbs_pcbspm_mode_reg:
.quad 0
/// \endcond
|