summaryrefslogtreecommitdiffstats
path: root/src/usr/hwpf/hwp/pstates/pstates/pstates.h
blob: c41484d6fced6d44fc5e67287381a94bf98b0064 (plain)
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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/usr/hwpf/hwp/pstates/pstates/pstates.h $                  */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* COPYRIGHT International Business Machines Corp. 2013,2014              */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
#ifndef __PSTATES_H__
#define __PSTATES_H__

// $Id: pstates.h,v 1.10 2013/10/04 18:38:18 jimyac Exp $

/// \file pstates.h
/// \brief Pstate structures and support routines for OCC product firmware

#include "pgp_common.h"

////////////////////////////////////////////////////////////////////////////
// Global and Local Pstate Tables
////////////////////////////////////////////////////////////////////////////

/// The Global Pstate Table must be 1KB-aligned in SRAM. The alignment is
/// specified in the traditional log2 form.
#define GLOBAL_PSTATE_TABLE_ALIGNMENT 10

/// The Global Pstate table has 128 * 8-byte entries
#define GLOBAL_PSTATE_TABLE_ENTRIES 128

/// The Local Pstate table has 32 x 64-bit entries
#define LOCAL_PSTATE_ARRAY_ENTRIES 32

/// The VDS/VIN table has 32 x 64-bit entries
#define VDSVIN_ARRAY_ENTRIES       64 

/// The VRM-11 VID base voltage in micro-Volts
#define VRM11_BASE_UV 1612500

/// The VRM-11 VID step as an unsigned number (micro-Volts)
#define VRM11_STEP_UV 6250

/// The iVID base voltage in micro-Volts
#define IVID_BASE_UV 600000

/// The iVID step as an unsigned number (micro-Volts)
#define IVID_STEP_UV 6250

///  CPM Inflection Points
#define CPM_RANGES 8

// Error/Panic codes for support routines

#define VRM11_INVALID_VOLTAGE 0x00876101

#define PSTATE_OVERFLOW  0x00778a01
#define PSTATE_UNDERFLOW 0x00778a02

#define PSTATE_LT_PSTATE_MIN 0x00778a03
#define PSTATE_GT_PSTATE_MAX 0x00778a04

#define DPLL_OVERFLOW  0x00d75501
#define DPLL_UNDERFLOW 0x00d75502

#define VID11_OVERFLOW  0x00843101
#define VID11_UNDERFLOW 0x00843102

#define GPST_INVALID_OBJECT      0x00477801
#define GPST_INVALID_ARGUMENT    0x00477802
#define GPST_INVALID_ENTRY       0x00477803
#define GPST_PSTATE_CLIPPED_LOW  0x00477804
#define GPST_PSTATE_CLIPPED_HIGH 0x00477805
#define GPST_BUG                 0x00477806
#define GPST_PSTATE_GT_GPST_PMAX 0x00477807

#define LPST_INVALID_OBJECT      0x00477901 
#define LPST_GPST_WARNING        0x00477902 
#define LPST_INCR_CLIP_ERROR     0x00477903

/// PstateSuperStructure Magic Number
///
/// This magic number identifies a particular version of the
/// PstateSuperStructure and its substructures.  The version number should be
/// kept up to date as changes are made to the layout or contents of the
/// structure. 

#define PSTATE_SUPERSTRUCTURE_MAGIC 0x5053544154453032ull /* PSTATE02 */


/// \defgroup pstate_options Pstate Options
///
/// These are flag bits for the \a options field of the PstateOptions
/// structure.
///
/// @{

/// gpsm_gpst_install() - Bypass copying the Pstate table from the
/// PstateSuperStructure into the aligned global location.
#define PSTATE_NO_COPY_GPST       0x01

/// gpsm_gpst_install() - Bypass Global Pstate Table installation and setup.
#define PSTATE_NO_INSTALL_GPST    0x02

/// gpsm_lpsa_install() - Bylass Local Pstate Array installation and setup
#define PSTATE_NO_INSTALL_LPSA    0x04

/// gpsm_resclk_install - Bypass resonant clocking Pstate limit setup
#define PSTATE_NO_INSTALL_RESCLK  0x08

/// gpsm_enable_pstates() - Force the system to the minimum Pstate at
/// initialization
///
/// This mode is added as a workaround for the case that the SPIVID interface
/// is not working correctly during initial bringup.  This forces Pstate mode
/// to come up at a low frequency.
#define PSTATE_FORCE_INITIAL_PMIN 0x10

/// @}

#ifndef __ASSEMBLER__

#include <stdint.h>

#include <p8_ivrm.H>

/// A Global Pstate Table Entry, in the form of a packed 'firmware register'
///
/// Global Pstate table entries are referenced by OCC firmware, for example
/// in procedures that do 'manual' Pstate manipulation.

typedef union gpst_entry {

    uint64_t value;
    struct {
#ifdef _BIG_ENDIAN
        uint32_t high_order;
        uint32_t low_order;
#else
        uint32_t low_order;
        uint32_t high_order;
#endif // _BIG_ENDIAN
    } words;
    struct {
#ifdef _BIG_ENDIAN
    uint64_t evid_vdd     : 8;
    uint64_t evid_vcs     : 8;
    uint64_t reserved16   : 1;
    uint64_t evid_vdd_eff : 7;
    uint64_t reserved24   : 1;
    uint64_t evid_vcs_eff : 7;
    uint64_t reserved32   : 1;
    uint64_t maxreg_vdd   : 7;
    uint64_t reserved40   : 1;
    uint64_t maxreg_vcs   : 7;
        uint64_t reserved48   : 8;
        uint64_t ecc          : 8;
#else
        uint64_t ecc          : 8;
        uint64_t reserved48   : 8;
    uint64_t maxreg_vcs   : 7;
    uint64_t reserved40   : 1;
    uint64_t maxreg_vdd   : 7;
    uint64_t reserved32   : 1;
    uint64_t evid_vcs_eff : 7;
    uint64_t reserved24   : 1;
    uint64_t evid_vdd_eff : 7;
    uint64_t reserved16   : 1;
    uint64_t evid_vcs     : 8;
    uint64_t evid_vdd     : 8;
#endif // _BIG_ENDIAN
    } fields;

} gpst_entry_t;


/// A Local Pstate Table Entry, in the form of a packed 'firmware register'
///
/// This structure is provided for reference only; Currently the OCC firmware
/// does not manupulate Local Pstate table entries, however it is possible
/// that future lab applications will require this.

typedef union lpst_entry {

    uint64_t value;
    struct {
#ifdef _BIG_ENDIAN
        uint32_t high_order;
        uint32_t low_order;
#else
        uint32_t low_order;
        uint32_t high_order;
#endif // _BIG_ENDIAN
    } words;
    struct {
#ifdef _BIG_ENDIAN
    uint64_t ivid_vdd          : 7;
    uint64_t ivid_vcs          : 7;
    uint64_t vdd_core_pwrratio : 6;
    uint64_t vcs_core_pwrratio : 6;
    uint64_t vdd_eco_pwrratio  : 6;
    uint64_t vcs_eco_pwrratio  : 6;
    uint64_t ps1_vid_incr      : 3;
    uint64_t ps2_vid_incr      : 3; 
    uint64_t ps3_vid_incr      : 3;
    uint64_t reserved47        : 7;
    uint64_t inc_step          : 3;
    uint64_t dec_step          : 3;
    uint64_t reserved60        : 4;
#else
    uint64_t reserved60        : 4;
    uint64_t dec_step          : 3;
    uint64_t inc_step          : 3;
    uint64_t reserved47        : 7;
    uint64_t ps3_vid_incr      : 3;
    uint64_t ps2_vid_incr      : 3; 
    uint64_t ps1_vid_incr      : 3;
    uint64_t vcs_eco_pwrratio  : 6;
    uint64_t vdd_eco_pwrratio  : 6;
    uint64_t vcs_core_pwrratio : 6;
    uint64_t vdd_core_pwrratio : 6;
    uint64_t ivid_vcs          : 7;
    uint64_t ivid_vdd          : 7;
#endif // _BIG_ENDIAN
    } fields;

} lpst_entry_t;


/// A VDS/VIN table Entry

typedef union vdsvin_entry {
    uint64_t value;
    struct {
#ifdef _BIG_ENDIAN
        uint32_t high_order;
        uint32_t low_order;
#else
        uint32_t low_order;
        uint32_t high_order;
#endif // _BIG_ENDIAN
    } words;
    struct {
#ifdef _BIG_ENDIAN
    uint64_t ivid0             : 7;
    uint64_t ivid1             : 7;
    uint64_t reserved14        : 2;    
    uint64_t pfet0             : 5; 
    uint64_t pfet1             : 5; 
    uint64_t pfet2             : 5; 
    uint64_t pfet3             : 5; 
    uint64_t pfet4             : 5; 
    uint64_t pfet5             : 5; 
    uint64_t pfet6             : 5; 
    uint64_t pfet7             : 5;
    uint64_t reserved_56       : 8;     
#else
    uint64_t reserved_56       : 8;
    uint64_t pfet7             : 5;    
    uint64_t pfet6             : 5;    
    uint64_t pfet5             : 5;    
    uint64_t pfet4             : 5;    
    uint64_t pfet3             : 5;    
    uint64_t pfet2             : 5;    
    uint64_t pfet1             : 5;    
    uint64_t pfet0             : 5;    
    uint64_t reserved14        : 2;    
    uint64_t ivid1             : 7;    
    uint64_t ivid0             : 7;    
#endif // _BIG_ENDIAN
    } fields;
} vdsvin_entry_t;

/// Standard options controlling Pstate setup and GPSM procedures

typedef struct {

    /// Option flags; See \ref pstate_options
    uint32_t options;

    /// Pad structure to 8 bytes.  Could also be used for other options later.
    uint32_t pad;

} PstateOptions;


/// An abstract Global Pstate table
///
/// The GlobalPstateTable is an abstraction of a set of voltage/frequency
/// operating points along with hardware limits.  Besides the hardware global
/// Pstate table, the abstract table contains enough extra information to make
/// it the self-contained source for setting up and managing voltage and
/// frequency in either Hardware or Firmware Pstate mode.
///
/// When installed in PMC, Global Pstate table indices are adjusted such that
/// the defined Pstates begin with table entry 0. The table need not be full -
/// the \a pmin and \a entries fields define the minimum and maximum Pstates
/// represented in the table.  However at least 1 entry must be defined to
/// create a legal table.
///
/// Note that Global Pstate table structures to be mapped into PMC hardware
/// must be 1KB-aligned.  This requirement is fullfilled by ensuring that
/// instances of this structure are 1KB-aligned.

typedef struct {

    /// The Pstate table
    gpst_entry_t pstate[GLOBAL_PSTATE_TABLE_ENTRIES];

    /// Pstate options
    ///
    /// The options are included as part of the GlobalPstateTable so that they
    /// are available to all procedures after gpsm_initialize().
    PstateOptions options;

    /// The frequency associated with Pstate[0] in KHz
    uint32_t pstate0_frequency_khz;

    /// The frequency step in KHz
    uint32_t frequency_step_khz;

    /// The DPLL frequency code corresponding to Pstate 0
    ///
    /// This frequency code is installed in the PCB Slave as the DPLL Fnom
    /// when the Pstate table is activated. Normally this frequency code is
    /// computed as
    ///
    ///     pstate0_frequency_khz / frequency_step_khz
    ///
    /// however it may be replaced by any other code as a way to
    /// transparently bias frequency on a per-core basis.
    DpllCode pstate0_frequency_code[PGP_NCORES];

    /// The DPLL Fmax bias
    ///
    /// This bias value (default 0, range -8 to +7 frequency ticks) is
    /// installed when the Pstate table is installed.  The value is allowed to
    /// vary per core.  This bias value will usually be set to a small
    /// positive number to provide a small amount of frequency headroom for
    /// the CPM-DPLL voltage control algorithm.
    ///
    /// \bug Hardware currently specifies this field as unsigned for the
    /// computation of frequency stability in
    /// dpll_freqout_mode_en. (HW217404).  This issue will be fixed in
    /// Venice. Since we never plan to use this mode no workaround or
    /// mitigation is provided by GPSM procedures.

    int8_t dpll_fmax_bias[PGP_NCORES];

    /// The number of entries defined in the table.
    uint8_t entries;

    /// The minimum Pstate in the table
    ///
    /// Note that gpsi_min = pmin - PSTATE_MIN, gpsi_max = pmin + entries - 1.
    Pstate pmin;

    /// The "Safe" Global Pstate
    ///
    /// This Pstate is installed in the PMC and represents the safe-mode
    /// voltage.
    Pstate pvsafe;

    /// The "Safe" Local Pstate
    ///
    /// This Pstate is installed in the PCB Slaves and represents the
    /// safe-mode frequency.
    Pstate psafe;

    /// Step size of Global Pstate steps
    uint8_t pstate_stepsize;

    /// The exponent of the exponential encoding of Pstate stepping delay
    uint8_t vrm_stepdelay_range;

    /// The significand of the exponential encoding of Pstate stepping delay
    uint8_t vrm_stepdelay_value;

    /// Pad structure to 8-byte alignment
    uint8_t pad;

} GlobalPstateTable;


/// This macro creates a properly-aligned Global Pstate table structure as a
/// static initialization.  

#define GLOBAL_PSTATE_TABLE(x)                                  \
    GlobalPstateTable x                                         \
    ALIGNED_ATTRIBUTE(POW2_32(GLOBAL_PSTATE_TABLE_ALIGNMENT))   \
        SECTION_ATTRIBUTE(".noncacheable")                      \
        = {.entries = 0}


/// An opaque Local Pstate Array
///
/// An array local to each core contains the Local Pstate Table, Vds table and
/// Vin table. The array contents are presented to OCC firmware as an opaque
/// set of 96 x 64-bit entries which are simply installed verbatim into each
/// core. Every core stores the same table.
///
/// When installed in the core, Local Pstate table indices are adjusted such
/// that the defined Pstates begin with table entry 0. The table need not be
/// full - the \a pmin and \a entries fields define the minimum and maximum
/// Pstates represented in the table.  However at least 1 entry must be
/// defined to create a legal table.

typedef struct {

    /// The vdsvin table contents
    vdsvin_entry_t vdsvin[VDSVIN_ARRAY_ENTRIES];

    /// The local pstate table contents
    lpst_entry_t pstate[LOCAL_PSTATE_ARRAY_ENTRIES];

    /// The number of entries defined in the Local Pstate Table
    uint8_t entries;

    /// The minimum Pstate in the Local Pstate table
    ///
    /// Note that lpsi_min = pmin - PSTATE_MIN, lpsi_max = pmin + entries - 1.
    Pstate pmin;

    /// Pstate step delay for rising iVRM voltages
    uint8_t stepdelay_rising;

    /// Pstate step delay for falling iVRM voltages
    uint8_t stepdelay_lowering;

    /// Pad structure to 8-byte alignment
    uint8_t pad[4];

} LocalPstateArray;


/// Resonant Clocking setup parameters
///
/// All Pstate parameters are specified in terms of Pstates as defined in the
/// current PstateSuperStructure.

typedef struct {

    /// Full Clock Sector Buffer Pstate
    Pstate full_csb_ps;

    /// Low-Frequency Resonant Lower Pstate
    Pstate res_low_lower_ps;

    /// Low-Frequency Resonant Upper Pstate
    Pstate res_low_upper_ps;

    /// High-Frequency Resonant Lower Pstate
    Pstate res_high_lower_ps;

    /// High-Frequency Resonant Upper Pstate
    Pstate res_high_upper_ps;

    /// Pad structure to 8-byte alignment
    uint8_t pad[3];

} ResonantClockingSetup;

/// CPM Pstate ranges per mode
///
/// These Pstate range specifications apply to all chiplets operating in the
/// same mode. 

typedef union {

    /// Forces alignment
    uint64_t quad[2];              

    struct {

        /// Lower limit of each CPM calibration range
        ///
        /// The entries in this table are Pstates representing the
        /// lowest-numbered (lowest-voltage) Pstate of each range. This is the
        /// inflection point between range N and range N+1.
        Pstate inflectionPoint[CPM_RANGES];

        /// The number of ranges valid in the \a inflectionPoint table
        ///
        /// Validity here is defined by the original characterization
        /// data. Whether or not OCC will use any particular range is managed
        /// by OCC.
        uint8_t validRanges;

        /// The Pstate corresponding to the upper limit of range 0.
        ///
        /// This is the "CPmax" for the mode. The "CPmin" for this
        /// mode is the value of inflectionPoint[valid_ranges - 1].
        Pstate pMax;
        
        uint8_t pad[6];
    };

} CpmPstateModeRanges;


/// The layout of the data created by the Pstate table creation firmware
///
/// This structure is only used for passing Pstate data from the FSP into OCC,
/// therefore there is no alignment requirement.  The \gpst member is copied
/// to an aligned location, and the \a lpsa and \a resclk members are directly
/// installed in hardware.
///
/// Both the master and slave OCCs (in DCM-mode) install their Pstate tables
/// independently via the API gpsm_initialize().  At that point the
/// PstateSuperStructure can be discarded.

typedef struct {

    /// Magic Number
    uint64_t magic;

    /// Global Pstate Table
    GlobalPstateTable gpst;

    /// Local Pstate Array
    LocalPstateArray lpsa;
    
    /// Resonant Clocking Setup
    ResonantClockingSetup resclk;
    
    /// CPM Pstate ranges
    CpmPstateModeRanges cpmranges;
  
} PstateSuperStructure;


int
vid11_validate(Vid11 vid);

int
bias_pstate(Pstate pstate, int bias, Pstate* biased_pstate);

int
bias_frequency(DpllCode fcode, int bias, DpllCode* biased_fcode);

int
bias_vid11(Vid11 vid, int bias, Vid11* biased_fcode);

int
gpst_entry(const GlobalPstateTable* gpst, 
           const Pstate pstate, 
           const int bias,
           gpst_entry_t* entry);


int 
freq2pState (const GlobalPstateTable* gpst, 
             const uint32_t freq_khz, 
             Pstate* pstate);
             
int
gpst_vdd2pstate(const GlobalPstateTable* gpst, 
                const uint8_t vdd, 
                Pstate* pstate,
                gpst_entry_t* entry);

int
pstate_minmax_chk (const GlobalPstateTable* gpst, 
                   Pstate* pstate);

/// Return the Pmin value associated with a GlobalPstateTable
static inline Pstate
gpst_pmin(const GlobalPstateTable* gpst)
{
    return gpst->pmin;
}


/// Return the Pmax value associated with a GlobalPstateTable
static inline Pstate
gpst_pmax(const GlobalPstateTable* gpst)
{
    return (int)(gpst->pmin) + (int)(gpst->entries) - 1;
}

/// Return the Pmin value associated with a LocalPstateTable
static inline Pstate
lpst_pmin(const LocalPstateArray* lpsa)
{
    return lpsa->pmin;
}


/// Return the Pmax value associated with a GlobalPstateTable
static inline Pstate
lpst_pmax(const LocalPstateArray* lpsa)
{
    return (int)(lpsa->pmin) + (int)(lpsa->entries) - 1;
}

#endif    /* __ASSEMBLER__ */

#endif    /* __PSTATES_H__ */
OpenPOWER on IntegriCloud