summaryrefslogtreecommitdiffstats
path: root/src/occ/amec/amec_init.c
blob: 7031eb02153e05fe15dcaedbbcdf35875087aaad (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
/******************************************************************************
// @file amec_init.c
// @brief OCC AMEC Initialization
*/
/******************************************************************************
 *
 *       @page ChangeLogs Change Logs
 *       @section amec_init.c AMEC_INIT.C
 *       @verbatim
 *
 *   Flag    Def/Fea    Userid    Date        Description
 *   ------- ---------- --------  ----------  ----------------------------------
 *   @th005             thallet   11/18/2011  Added this file
 *   @th00a             thallet   02/03/2012  Worst case FW timings in AMEC Sensors
 *   @th00b             thallet   02/28/2012  Added functions to init vector sensors
 *   @rc003             rickylie  02/03/2012  Verify & Clean Up OCC Headers & Comments
 *   @pb00E             pbavari   03/11/2012  Added correct include file
 *   @nh001             neilhsu   05/23/2012  Add missing error log tags 
 *   @gs001             gsilva    08/03/2012  Added g_amec init function
 *   @ly001  853751     lychen    09/17/2012  Support DPS algorithm
 *   @ry002  822116     ronda     11/26/2012  Support thermal controller for processor
 *   @ry003  870734     ronda     02/20/2013  Thermal controller for memory 
 *   @fk001  879727     fmkassem  04/16/2013  PCAP support. 
 *   @cl001             lefurgy   07/24/2013  Fix thermal control loop
 *   @gm006  SW224414   milesg    09/16/2013  Reset and FFDC improvements 
 *   @gm008  SW226989   milesg    09/30/2013  Sapphire initial support
 *   @gs023  912003     gjsilva   01/16/2014  Generate VRHOT signal and control loop
 *   @mw641  918066     mware     02/23/2014  g44_avg changed to 32 bits. Altered zeroing out of array at init.
 *
 *  @endverbatim
 *
 *///*************************************************************************/

//*************************************************************************
// Includes
//*************************************************************************
//@pb00Ec - changed from common.h to occ_common.h for ODE support
#include <occ_common.h>
#include <amec_sys.h>
#include <ssx.h>         
#include <errl.h>               // Error logging
#include <rtls.h>
#include <occ_sys_config.h>
#include <occ_service_codes.h>  // for SSX_GENERIC_FAILURE
#include <trac.h>
#include "state.h"
#include "amec_service_codes.h"
#include <amec_sys.h>
#include <proc_data.h>
#include <sensor.h>

//*************************************************************************
// Externs
//*************************************************************************

//*************************************************************************
// Macros
//*************************************************************************

//*************************************************************************
// Defines/Enums
//*************************************************************************

//*************************************************************************
// Structures
//*************************************************************************

//*************************************************************************
// Globals
//*************************************************************************
// We can initialize amec system structure to all zeros
amec_sys_t g_amec_sys = {0}; //@gm008

// Initialize g_amec to point to g_amec_sys
// We use this pointer to keep the amec code as similar to TPMD
amec_sys_t * g_amec = &g_amec_sys;

// GPE Request Structure that is used to measure the worst case GPE timings
PoreFlex G_gpe_nop_request[NUM_GPE_ENGINES];         // @th00a

extern PoreEntryPoint GPE_pore_nop;    // @th00a
extern void amec_slv_update_gpe_sensors(uint8_t i_gpe_engine);   // @th00a
extern void amec_slv_update_gpe_sensors(uint8_t i_gpe_engine);   // @th00a

//*************************************************************************
// Function Prototypes
//*************************************************************************

//*************************************************************************
// Functions
//*************************************************************************
void amec_vectorize_core_sensor(sensor_t * l_sensor, 
                                vectorSensor_t * l_vector,
                                const VECTOR_SENSOR_OP l_op,
                                uint16_t l_sensor_elem_array_gsid)
{
#define VECTOR_CREATE_FAILURE   1
#define VECTOR_ADD_ELEM_FAILURE 2

  int l_idx = 0;    // Used to index the for loops for vector create
  int l_rc  = 0;                // Indicates failure to add a sensor to vector 
  uint16_t l_gsid  = 0xFFFF;
  errlHndl_t l_err = NULL;

  do
  {
    // Grab GSID for errl in case of failure
    l_gsid = l_sensor->gsid;

    // Vectorize the sensor
    sensor_vectorize(l_sensor,
        l_vector,
        l_op);

    // If vectorize worked, add elements to the vector sensor
    if(NULL != l_sensor->vector)
    {
      // Loop through cores
      for(l_idx=0; l_idx<MAX_NUM_CORES; l_idx++)
      {
        // Add elements to the vector sensor
        sensor_vector_elem_add(l_sensor->vector,
            l_idx,
            AMECSENSOR_ARRAY_PTR(l_sensor_elem_array_gsid,l_idx));
        // If core is not present, disable this vector element
        if(!CORE_PRESENT(l_idx))
        {
          sensor_vector_elem_enable(l_sensor->vector,
              l_idx,
              0 /* Disable */);
        }
      }

      // Sanity check, we should have MAX_NUM_CORES entries in 
      // vector sensor
      if(l_sensor->vector->size != MAX_NUM_CORES)
      {
        // Set l_rc and break out so that we can create an errl
        l_rc = VECTOR_ADD_ELEM_FAILURE;
        break;
      }
    }
    else
    {
      // Set l_rc and break out so that we can create an errl
      l_rc = VECTOR_CREATE_FAILURE;
      break;
    } 
  }while(0);

  if(l_rc)
  {
    //If fail to create pore flex object then there is a problem.
    TRAC_ERR("Failed to vectorize sensor[0x%x, 0x%x]", l_gsid, l_rc );

    /* @
     * @errortype
     * @moduleid    AMEC_VECTORIZE_FW_SENSORS
     * @reasoncode  SSX_GENERIC_FAILURE
     * @userdata1   return code
     * @userdata2   gsid of failed sensor
     * @userdata4   OCC_NO_EXTENDED_RC
     * @devdesc     Firmware failure in call to vectorize sensor 
     */
    l_err = createErrl(
        AMEC_VECTORIZE_FW_SENSORS,      //modId
        SSX_GENERIC_FAILURE,            //reasoncode
        OCC_NO_EXTENDED_RC,             //Extended reason code
        ERRL_SEV_UNRECOVERABLE,         //Severity
        NULL,//TODO: create trace       //Trace Buf
        DEFAULT_TRACE_SIZE,             //Trace Size
        l_rc,                           //userdata1
        l_gsid                          //userdata2
        );

    REQUEST_RESET(l_err);  //gm06
  }
}

void amec_init_vector_sensors(void)
{

#define VECTOR_CREATE_FAILURE   1
#define VECTOR_ADD_ELEM_FAILURE 2

  //-----------------------------------------------------
  // TEMP2MSP0 Vector Sensor
  //-----------------------------------------------------
  amec_vectorize_core_sensor(AMECSENSOR_PTR(TEMP2MSP0), 
      &g_amec_sys.proc[0].temp2ms_vector, 
      VECTOR_OP_AVG,
      TEMP2MSP0C0);

  //-----------------------------------------------------
  // FREQA2MSP0 Vector Sensor
  //-----------------------------------------------------
  amec_vectorize_core_sensor(AMECSENSOR_PTR(FREQA2MSP0),    // @mw626
      &g_amec_sys.proc[0].freqa2ms_vector, 
      VECTOR_OP_AVG,
      FREQA2MSP0C0);

  //-----------------------------------------------------
  // IPS2MSP0 Vector Sensor
  //-----------------------------------------------------
  amec_vectorize_core_sensor(AMECSENSOR_PTR(IPS2MSP0), 
      &g_amec_sys.proc[0].ips2ms_vector, 
      VECTOR_OP_AVG,
      IPS2MSP0C0);

  //-----------------------------------------------------
  // TEMP2MSP0PEAK Vector Sensor
  //-----------------------------------------------------
  amec_vectorize_core_sensor(AMECSENSOR_PTR(TEMP2MSP0PEAK), 
      &g_amec_sys.proc[0].temp2mspeak_vector, 
      VECTOR_OP_MAX,
      TEMP2MSP0C0);

  //-----------------------------------------------------
  // UTIL2MSP0 Vector Sensor
  //-----------------------------------------------------
  amec_vectorize_core_sensor(AMECSENSOR_PTR(UTIL2MSP0), 
      &g_amec_sys.proc[0].util2ms_vector, 
      VECTOR_OP_AVG,
      UTIL2MSP0C0);

#if 0  //TODO: Re-enable with error checking when centaur support is added
  int l_rc = 0, l_idx = 0, l_idx2 = 0;    // Used to index the for loops for vector create
  //-----------------------------------------------------
  // MEMSP2MSP0 Vector Sensor
  //-----------------------------------------------------
  sensor_vectorize(AMECSENSOR_PTR(MEMSP2MSP0),
      &g_amec_sys.proc[0].memsp2ms_vector,
      VECTOR_OP_MIN);

  for(l_idx=0; l_idx<MAX_NUM_MEM_CONTROLLERS; l_idx++)
  {
    for(l_idx2=0; l_idx2<NUM_PORT_PAIRS_PER_CENTAUR; l_idx2++)
    {
      sensor_vector_elem_add(AMECSENSOR_PTR(MEMSP2MSP0)->vector,
          l_idx,
          AMECSENSOR_2D_ARRAY_PTR(MEMSP2MSPM0C0P0,l_idx, l_idx2));      
    }
  }
#endif
}

// Function Specification
//
// Name:  amec_init_gamec_struct
//
// Description:  Perform initialization of g_amec structure
//
// Flow:  --/--/--    FN=a
//
// End Function Specification
void amec_init_gamec_struct(void)
{
  /*------------------------------------------------------------------------*/
  /*  Local Variables                                                       */
  /*------------------------------------------------------------------------*/
  uint16_t l_idx = 0; // @ly001a

  /*------------------------------------------------------------------------*/
  /*  Code                                                                  */
  /*------------------------------------------------------------------------*/

  // Defaul the frequency range to something safe
  g_amec->sys.fmin = 2000;
  g_amec->sys.fmax = 2000;
  g_amec->sys.max_speed = 1000; // @ly001a
  
  g_amec->sys.min_speed = 400;
  g_amec->sys.speed_step = 10;
  g_amec->sys.speed_step_limit = (uint16_t)((65535/4)/(g_amec->sys.speed_step));
  
  // Initialize thermal controller for processor
  g_amec->thermalproc.setpoint = 850; // @cl001 change to 850 = 85.0 C
  g_amec->thermalproc.Pgain = 1000;
  g_amec->thermalproc.speed_request = 1000;
  g_amec->thermalproc.freq_request = -1; //unconstrained frequency vote
  g_amec->thermalproc.total_res = 0;
  
  // Initialize thermal controller based on DIMM temperatures
  g_amec->thermaldimm.setpoint = 850; //In 0.1 degrees C @cl001 change to 850 = 85.0 C
  g_amec->thermaldimm.Pgain = 30000;
  g_amec->thermaldimm.speed_request = AMEC_MEMORY_MAX_STEP;

  // Initialize thermal controller based on Centaur temperatures
  g_amec->thermalcent.setpoint = 850; //In 0.1 degrees C @cl001 change to 850 = 85.0 C
  g_amec->thermalcent.Pgain = 30000;
  g_amec->thermalcent.speed_request = AMEC_MEMORY_MAX_STEP;
  
  // Initialize controler based on VRHOT signal from processor regulator
  g_amec->vrhotproc.setpoint = 100;
  g_amec->vrhotproc.freq_request = -1;
  g_amec->vrhotproc.speed_request = 1000;

  // @ly001a - start
  // Initialize partition information
  amec_part_init();

  // Initialize performace counter
  for (l_idx=0; l_idx<MAX_NUM_CORES; l_idx++)
  {
    amec_core_perf_counter_ctor(&g_amec->proc[0].core[l_idx].core_perf, 0, l_idx);
  }
  // @ly001a - end

  //Initialize processor fields
  g_amec->proc[0].core_max_freq = G_sysConfigData.sys_mode_freq.table[OCC_MODE_TURBO];

  //Initialize processor power votes
  g_amec->proc[0].pwr_votes.pmax_clip_freq = G_sysConfigData.sys_mode_freq.table[OCC_MODE_TURBO];

  //Initialize stream buffer recording parameters
  g_amec->recordflag=0;      // Never enable recording until requested via Amester API call
  g_amec->r_cnt=0;           // Reset counter of 250us ticks   
  g_amec->ptr_stream_buffer = &g_amec->stream_buffer[0];  
  g_amec->stream_vector_mode=0;      // No recording yet
  g_amec->stream_vector_delay=0;     // Delay in msec before recording can begin
  g_amec->stream_vector_rate=0xff;   // Invalid setting: requires IPMI command to select initial rate

  //Initialize analytics parameters
  g_amec->analytics_group=44;        // Default to analytics Group 44   $mw431  
  g_amec->analytics_chip=0;          // Default to which chip to perform analytics on $mw417
  g_amec->analytics_bad_output_count=0;   // Number of frames to discard before recording analytics output @mw587
  g_amec->analytics_total_chips=MAX_NUM_CHIP_MODULES;  // Default to do all chips in the system $mw418
  g_amec->analytics_threadmode=1;  // Default is average of all N threads  $mw470 (may be altered with IPMI command)
  g_amec->analytics_threadcountmax=4;  // Default is 4 threads per core  $mw459 (may be altered with IPMI command)
  g_amec->analytics_total_chips=4;    // For Tuleta force to only 2 DCM sockets, 4 chips
  g_amec->analytics_option=1;         // =0 means cycle through all chips, =1 means only work with analytics_chip 
  g_amec->analytics_thermal_offset=0;  // Reset offset to 0 for thermal output group
  g_amec->analytics_slot=4;       // Time slot associated with when the amec_analytics function is called (out of 8 slots) @mw586
  // Set entire averaging buffer to zero $mw417
  memset (&g_amec->g44_avg, 0, 4*(MAX_SENSORS_ANALYTICS*MAX_NUM_CHIP_MODULES));    // @mw641
}

// Function Specification
//
// Name:  amec_slave_init
//
// Description:  Perform initialization of any/all AMEC Slave Functions
//
// Flow:  2/01/12    FN=amec_slave_init
//
// End Function Specification

void amec_slave_init()
{
  errlHndl_t l_err = NULL;   // Error handler
  int         rc   = 0;         // Return code
  int         rc2  = 0;         // Return code

  // Set the GPE Request Pointers to NULL in case the create fails.
  G_fw_timing.gpe0_timing_request = NULL;
  G_fw_timing.gpe1_timing_request = NULL;

  // Initializes the GPE routine that will be used to measure the worst case 
  // timings for GPE0
  rc  = pore_flex_create( &G_gpe_nop_request[0],        //gpe_req for the task
                          &G_pore_gpe0_queue,           //queue
                          (void *) GPE_pore_nop,        //entry point
                          (uint32_t)  NULL,             //parm for the task
                          SSX_WAIT_FOREVER,             //no timeout
                          (AsyncRequestCallback) amec_slv_update_gpe_sensors,    //callback
                          (void *) GPE_ENGINE_0,        //callback argument
                          ASYNC_CALLBACK_IMMEDIATE );   //options

  // Initializes the GPE routine that will be used to measure the worst case 
  // timings for GPE1
  rc2 = pore_flex_create( &G_gpe_nop_request[1],        //gpe_req for the task
                          &G_pore_gpe1_queue,           //queue
                          (void *)GPE_pore_nop,         //entry point
                          (uint32_t) NULL,              //parm for the task
                          SSX_WAIT_FOREVER,             //no timeout
                          (AsyncRequestCallback) amec_slv_update_gpe_sensors,    //callback
                          (void *) GPE_ENGINE_1,        //callback argument
                          ASYNC_CALLBACK_IMMEDIATE );   //options

  // If we couldn't create the poreFlex objects, there must be a major problem
  // so we will log an error and halt OCC.
  if( rc || rc2 )
  {
    //If fail to create pore flex object then there is a problem.
    TRAC_ERR("Failed to create GPE duration poreFlex object[0x%x, 0x%x]", rc, rc2 );

    /* @
     * @errortype
     * @moduleid    AMEC_INITIALIZE_FW_SENSORS
     * @reasoncode  SSX_GENERIC_FAILURE
     * @userdata1   return code - gpe0
     * @userdata2   return code - gpe1
     * @userdata4   OCC_NO_EXTENDED_RC
     * @devdesc     Failure to create PORE-GPE poreFlex object for FW timing
     *              analysis. 
     *              
     */
    l_err = createErrl(
        AMEC_INITIALIZE_FW_SENSORS,         //modId
        SSX_GENERIC_FAILURE,                //reasoncode
        OCC_NO_EXTENDED_RC,                 //Extended reason code
        ERRL_SEV_PREDICTIVE,                //Severity
        NULL,    //TODO: create trace       //Trace Buf
        DEFAULT_TRACE_SIZE,                 //Trace Size
        rc,                                 //userdata1
        rc2                                 //userdata2
    );                                      

    REQUEST_RESET(l_err); //gm06
    
  }
  else
  {
    // Everything was successful, so set FW timing pointers to these 
    // GPE Request objects
    G_fw_timing.gpe0_timing_request = &G_gpe_nop_request[0];
    G_fw_timing.gpe1_timing_request = &G_gpe_nop_request[1];
  }

  // Initialize Vector Sensors for AMEC use
  amec_init_vector_sensors();     // @th00b

  // Initialize AMEC internal parameters
  amec_init_gamec_struct();
}

OpenPOWER on IntegriCloud