summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorShawn McCarney <shawnmm@us.ibm.com>2017-07-12 16:19:54 -0500
committerMartha Broyles <mbroyles@us.ibm.com>2017-08-02 16:28:58 -0400
commit9b64b7c93ac21aaac19c98eda502ad00b1454120 (patch)
tree91302fdf03eb18d6995bbb9776e82c5765064761 /src
parent2c6661b3dcabd0aa3a69c3aeb34c760638da4064 (diff)
downloadtalos-occ-9b64b7c93ac21aaac19c98eda502ad00b1454120.tar.gz
talos-occ-9b64b7c93ac21aaac19c98eda502ad00b1454120.zip
Timestamp data when collected
This commit contains the following enhancements: * New IPC function that runs on GPE0 to read the TOD (Time Of Day) registers * New task on the OCC 405 that gets current TOD every tick via IPC function * Sensor update function now sets timestamp to current TOD value Change-Id: I0ea42b01e4df7a93633a68a0f3ed0f839d5e7b3f RTC: 176504 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/43891 Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com> Reviewed-by: William A. Bryan <wilbryan@us.ibm.com> Reviewed-by: Martha Broyles <mbroyles@us.ibm.com>
Diffstat (limited to 'src')
-rw-r--r--src/common/get_tod_structs.h50
-rw-r--r--src/common/ipc_func_ids.h1
-rwxr-xr-xsrc/common/pss_constants.h7
-rw-r--r--src/occ_405/occLinkInputFile1
-rwxr-xr-xsrc/occ_405/rtls/rtls.h1
-rwxr-xr-xsrc/occ_405/rtls/rtls_tables.c21
-rwxr-xr-xsrc/occ_405/sensor/sensor.c8
-rwxr-xr-xsrc/occ_405/sensor/sensor.h4
-rw-r--r--src/occ_405/sensor/sensor_get_tod_task.c482
-rw-r--r--src/occ_405/sensor/sensor_get_tod_task.h54
-rw-r--r--src/occ_405/sensor/sensor_main_memory.c1
-rwxr-xr-xsrc/occ_405/sensor/sensor_service_codes.h5
-rw-r--r--src/occ_405/topfiles.mk1
-rw-r--r--src/occ_gpe0/gpe_get_tod.c154
-rw-r--r--src/occ_gpe0/ipc_func_tables.c5
-rw-r--r--src/occ_gpe0/topfiles.mk5
16 files changed, 789 insertions, 11 deletions
diff --git a/src/common/get_tod_structs.h b/src/common/get_tod_structs.h
new file mode 100644
index 0000000..7312a6f
--- /dev/null
+++ b/src/common/get_tod_structs.h
@@ -0,0 +1,50 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/common/get_tod_structs.h $ */
+/* */
+/* OpenPOWER OnChipController Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2017,2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* 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 */
+
+/* This header file is used by both occ_405 and occ_gpe0. */
+/* Contains common structures and defines. */
+
+#ifndef _GET_TOD_STRUCTS_H
+#define _GET_TOD_STRUCTS_H
+
+#include <stdint.h> // For uint*_t
+#include <gpe_export.h> // For GpeErrorStruct
+
+/**
+ * Struct containing the error state and arguments for the IPC function
+ * IPC_ST_GET_TOD_FUNCID.
+ */
+typedef struct __attribute__ ((packed))
+{
+ GpeErrorStruct error;
+ uint64_t tod;
+} gpe_get_tod_args_t;
+
+/**
+ * Value used when the actual TOD value is unknown.
+ */
+#define TOD_VALUE_UNKNOWN 0xFFFFFFFFFFFFFFFFull
+
+#endif // _GET_TOD_STRUCTS_H
diff --git a/src/common/ipc_func_ids.h b/src/common/ipc_func_ids.h
index 40842be..3f759a5 100644
--- a/src/common/ipc_func_ids.h
+++ b/src/common/ipc_func_ids.h
@@ -60,6 +60,7 @@ IPC_FUNCIDS_TABLE_START
IPC_FUNC_ID(IPC_ST_GPE0_NOP)
IPC_FUNC_ID(IPC_ST_GET_NEST_DTS_FUNCID)
IPC_FUNC_ID(IPC_ST_FIR_COLLECTION)
+ IPC_FUNC_ID(IPC_ST_GET_TOD_FUNCID)
IPC_FUNCIDS_ST_END(OCCHW_INST_ID_GPE0)
//Functions that are only supported by GPE1 should be defined here
diff --git a/src/common/pss_constants.h b/src/common/pss_constants.h
index 08a7d90..8ce9bb5 100755
--- a/src/common/pss_constants.h
+++ b/src/common/pss_constants.h
@@ -1,11 +1,11 @@
/* IBM_PROLOG_BEGIN_TAG */
/* This is an automatically generated prolog. */
/* */
-/* $Source: src/occ_gpe0/pss_constants.h $ */
+/* $Source: src/common/pss_constants.h $ */
/* */
/* OpenPOWER OnChipController Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2011,2016 */
+/* Contributors Listed Below - COPYRIGHT 2011,2017 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -52,7 +52,8 @@
#define SPIPSS_P2S_WDATA_REG (SPIPSS_REGISTER_BASE + 0x50)
#define SPIPSS_P2S_RDATA_REG (SPIPSS_REGISTER_BASE + 0x60)
-#define TOD_VALUE_REG 0x00040020
+#define TOD_STATUS_REG 0x00040008
+#define TOD_VALUE_REG 0x00040020
// Constant for use in wait statments: waits (5 * MICROSECONDS)
#define MICROSECONDS 600
diff --git a/src/occ_405/occLinkInputFile b/src/occ_405/occLinkInputFile
index 9f3725d..123a0dc 100644
--- a/src/occ_405/occLinkInputFile
+++ b/src/occ_405/occLinkInputFile
@@ -80,6 +80,7 @@ INPUT ( amec_amester.o
reset.o
rtls_tables.o
rtls.o
+ sensor_get_tod_task.o
sensor_inband_cmd.o
sensor_info.o
sensor_main_memory.o
diff --git a/src/occ_405/rtls/rtls.h b/src/occ_405/rtls/rtls.h
index 2b8fbae..899d44a 100755
--- a/src/occ_405/rtls/rtls.h
+++ b/src/occ_405/rtls/rtls.h
@@ -62,6 +62,7 @@ typedef enum {
TASK_ID_NEST_DTS,
TASK_ID_24X7, // 24x7 data collection task
TASK_ID_GPE_TIMINGS,
+ TASK_ID_GET_TOD, // Get time of day task
TASK_END // This must always be the last enum in this list,
// so that TASK_END always equals the last task ID + 1.
} task_id_t;
diff --git a/src/occ_405/rtls/rtls_tables.c b/src/occ_405/rtls/rtls_tables.c
index 2f67e5c..eb439cf 100755
--- a/src/occ_405/rtls/rtls_tables.c
+++ b/src/occ_405/rtls/rtls_tables.c
@@ -37,6 +37,7 @@
#include "amec_sensors_fw.h"
#include "dimm.h"
#include <common.h>
+#include "sensor_get_tod_task.h" // For task_get_tod()
//flags for task table
#define APSS_TASK_FLAGS RTL_FLAG_MSTR | RTL_FLAG_OBS | RTL_FLAG_ACTIVE | RTL_FLAG_MSTR_READY | RTL_FLAG_RUN
@@ -62,8 +63,9 @@
#define FLAGS_AMEC_SLAVE RTL_FLAG_MSTR | RTL_FLAG_NOTMSTR | RTL_FLAG_OBS | RTL_FLAG_ACTIVE | RTL_FLAG_MSTR_READY | RTL_FLAG_NO_APSS | RTL_FLAG_RUN | RTL_FLAG_APSS_NOT_INITD
#define FLAGS_AMEC_MASTER RTL_FLAG_MSTR | RTL_FLAG_OBS | RTL_FLAG_ACTIVE | RTL_FLAG_MSTR_READY | RTL_FLAG_NO_APSS | RTL_FLAG_RUN | RTL_FLAG_APSS_NOT_INITD
-#define FLAGS_24X7 RTL_FLAG_MSTR | RTL_FLAG_NOTMSTR | RTL_FLAG_OBS | RTL_FLAG_ACTIVE | RTL_FLAG_MSTR_READY | RTL_FLAG_NO_APSS | RTL_FLAG_RUN | RTL_FLAG_APSS_NOT_INITD
+#define FLAGS_24X7 RTL_FLAG_MSTR | RTL_FLAG_NOTMSTR | RTL_FLAG_OBS | RTL_FLAG_ACTIVE | RTL_FLAG_MSTR_READY | RTL_FLAG_NO_APSS | RTL_FLAG_RUN | RTL_FLAG_APSS_NOT_INITD
+#define FLAGS_GET_TOD RTL_FLAG_MSTR | RTL_FLAG_NOTMSTR | RTL_FLAG_OBS | RTL_FLAG_ACTIVE | RTL_FLAG_MSTR_READY | RTL_FLAG_NO_APSS | RTL_FLAG_RUN | RTL_FLAG_APSS_NOT_INITD
#define FLAGS_APSS_START_MEAS APSS_TASK_FLAGS
#define FLAGS_APSS_CONT_MEAS APSS_TASK_FLAGS
@@ -127,10 +129,12 @@ task_t G_task_table[TASK_END] = {
{ FLAGS_NEST_DTS, task_nest_dts, NULL },
{ FLAGS_24X7, task_24x7, NULL }, // TASK_ID_24X7
{ FLAGS_GPE_TIMINGS, task_gpe_timings, NULL }, // TASK_ID_GPE_TIMINGS
+ { FLAGS_GET_TOD, task_get_tod, NULL }, // TASK_ID_GET_TOD
};
const uint8_t G_tick0_seq[] = {
TASK_ID_APSS_START,
+ TASK_ID_GET_TOD,
TASK_ID_CORE_DATA_LOW,
TASK_ID_DIMM_SM,
TASK_ID_APSS_CONT,
@@ -153,6 +157,7 @@ const uint8_t G_tick0_seq[] = {
const uint8_t G_tick1_seq[] = {
TASK_ID_APSS_START,
+ TASK_ID_GET_TOD,
TASK_ID_CORE_DATA_LOW,
//TASK_ID_GPU_SM,
TASK_ID_APSS_CONT,
@@ -175,6 +180,7 @@ const uint8_t G_tick1_seq[] = {
const uint8_t G_tick2_seq[] = {
TASK_ID_APSS_START,
+ TASK_ID_GET_TOD,
TASK_ID_CORE_DATA_LOW,
TASK_ID_DIMM_SM,
TASK_ID_APSS_CONT,
@@ -197,6 +203,7 @@ const uint8_t G_tick2_seq[] = {
const uint8_t G_tick3_seq[] = {
TASK_ID_APSS_START,
+ TASK_ID_GET_TOD,
TASK_ID_NEST_DTS,
//TASK_ID_GPU_SM,
TASK_ID_APSS_CONT,
@@ -219,6 +226,7 @@ const uint8_t G_tick3_seq[] = {
const uint8_t G_tick4_seq[] = {
TASK_ID_APSS_START,
+ TASK_ID_GET_TOD,
TASK_ID_CORE_DATA_LOW,
TASK_ID_DIMM_SM,
TASK_ID_APSS_CONT,
@@ -241,6 +249,7 @@ const uint8_t G_tick4_seq[] = {
const uint8_t G_tick5_seq[] = {
TASK_ID_APSS_START,
+ TASK_ID_GET_TOD,
TASK_ID_CORE_DATA_LOW,
//TASK_ID_GPU_SM,
TASK_ID_APSS_CONT,
@@ -263,6 +272,7 @@ const uint8_t G_tick5_seq[] = {
const uint8_t G_tick6_seq[] = {
TASK_ID_APSS_START,
+ TASK_ID_GET_TOD,
TASK_ID_CORE_DATA_LOW,
TASK_ID_DIMM_SM,
TASK_ID_APSS_CONT,
@@ -285,6 +295,7 @@ const uint8_t G_tick6_seq[] = {
const uint8_t G_tick7_seq[] = {
TASK_ID_APSS_START,
+ TASK_ID_GET_TOD,
//TASK_ID_GPU_SM,
TASK_ID_APSS_CONT,
TASK_ID_CORE_DATA_HIGH,
@@ -306,6 +317,7 @@ const uint8_t G_tick7_seq[] = {
const uint8_t G_tick8_seq[] = {
TASK_ID_APSS_START,
+ TASK_ID_GET_TOD,
TASK_ID_CORE_DATA_LOW,
TASK_ID_DIMM_SM,
TASK_ID_APSS_CONT,
@@ -328,6 +340,7 @@ const uint8_t G_tick8_seq[] = {
const uint8_t G_tick9_seq[] = {
TASK_ID_APSS_START,
+ TASK_ID_GET_TOD,
TASK_ID_CORE_DATA_LOW,
//TASK_ID_GPU_SM,
TASK_ID_APSS_CONT,
@@ -350,6 +363,7 @@ const uint8_t G_tick9_seq[] = {
const uint8_t G_tick10_seq[] = {
TASK_ID_APSS_START,
+ TASK_ID_GET_TOD,
TASK_ID_CORE_DATA_LOW,
TASK_ID_DIMM_SM,
TASK_ID_APSS_CONT,
@@ -372,6 +386,7 @@ const uint8_t G_tick10_seq[] = {
const uint8_t G_tick11_seq[] = {
TASK_ID_APSS_START,
+ TASK_ID_GET_TOD,
//TASK_ID_GPU_SM,
TASK_ID_APSS_CONT,
TASK_ID_CORE_DATA_HIGH,
@@ -393,6 +408,7 @@ const uint8_t G_tick11_seq[] = {
const uint8_t G_tick12_seq[] = {
TASK_ID_APSS_START,
+ TASK_ID_GET_TOD,
TASK_ID_CORE_DATA_LOW,
TASK_ID_DIMM_SM,
TASK_ID_APSS_CONT,
@@ -415,6 +431,7 @@ const uint8_t G_tick12_seq[] = {
const uint8_t G_tick13_seq[] = {
TASK_ID_APSS_START,
+ TASK_ID_GET_TOD,
TASK_ID_CORE_DATA_LOW,
//TASK_ID_GPU_SM,
TASK_ID_APSS_CONT,
@@ -437,6 +454,7 @@ const uint8_t G_tick13_seq[] = {
const uint8_t G_tick14_seq[] = {
TASK_ID_APSS_START,
+ TASK_ID_GET_TOD,
TASK_ID_CORE_DATA_LOW,
TASK_ID_DIMM_SM,
TASK_ID_APSS_CONT,
@@ -459,6 +477,7 @@ const uint8_t G_tick14_seq[] = {
const uint8_t G_tick15_seq[] = {
TASK_ID_APSS_START,
+ TASK_ID_GET_TOD,
//TASK_ID_GPU_SM,
TASK_ID_APSS_CONT,
TASK_ID_CORE_DATA_HIGH,
diff --git a/src/occ_405/sensor/sensor.c b/src/occ_405/sensor/sensor.c
index 73c2a5e..9863f1e 100755
--- a/src/occ_405/sensor/sensor.c
+++ b/src/occ_405/sensor/sensor.c
@@ -32,13 +32,15 @@
#include <occ_service_codes.h> // OCC reason codes
#include <sensor_service_codes.h> // sensor module ids
#include <trac.h> // Trace macros
-#include <rtls.h> // For G_current_tick
+#include <get_tod_structs.h> // For TOD_VALUE_UNKNOWN
#define UINT16_MIN 0
// Global sensor counter
uint32_t G_amec_sensor_count = 0;
+// See header file for description
+volatile uint64_t G_tod = TOD_VALUE_UNKNOWN;
void sensor_init(sensor_t * io_sensor_ptr,
const uint16_t i_gsid,
@@ -268,8 +270,8 @@ void sensor_update( sensor_t * io_sensor_ptr, const uint16_t i_sensor_value)
sensor_reset(io_sensor_ptr);
}
- // update timestamp
- io_sensor_ptr->timestamp = G_current_tick;
+ // set timestamp to current time of day
+ io_sensor_ptr->timestamp = G_tod;
// update sample value
io_sensor_ptr->sample = i_sensor_value;
diff --git a/src/occ_405/sensor/sensor.h b/src/occ_405/sensor/sensor.h
index 3b301d9..33f5e75 100755
--- a/src/occ_405/sensor/sensor.h
+++ b/src/occ_405/sensor/sensor.h
@@ -239,6 +239,10 @@ extern const sensor_info_t G_sensor_info[];
// Contains array of pointers to mini-sensors, indexed by GSID
extern const minisensor_ptr_t G_amec_mini_sensor_list[];
+// Current Time Of Day (TOD). Constantly updated by TASK_ID_GET_TOD. Used by
+// sensor_update(). Declared volatile since it is used in multiple threads.
+extern volatile uint64_t G_tod;
+
// sensor_init
void sensor_init(sensor_t * io_sensor_ptr,
const uint16_t i_gsid,
diff --git a/src/occ_405/sensor/sensor_get_tod_task.c b/src/occ_405/sensor/sensor_get_tod_task.c
new file mode 100644
index 0000000..eb511dc
--- /dev/null
+++ b/src/occ_405/sensor/sensor_get_tod_task.c
@@ -0,0 +1,482 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/occ_405/sensor/sensor_get_tod_task.c $ */
+/* */
+/* OpenPOWER OnChipController Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2017,2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* 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 */
+
+/**
+ * @file sensor_get_tod_task.c
+ *
+ * This file defines the functions and global variables for the task that gets
+ * the current Time Of Day (TOD).
+ *
+ * The register holding the time of day value is read via a SCOM address, and
+ * the OCC 405 cannot read from this address. To work around this, the IPC
+ * framework is used to request GPE0 to read the register value. GPE0 returns
+ * the current time of day value using a GPE_BUFFER.
+ */
+
+//******************************************************************************
+// Includes
+//******************************************************************************
+#include <sensor_get_tod_task.h> // Primary header
+#include <stdint.h> // For uint*_t
+#include <common_types.h> // For bool
+#include <sensor.h> // For G_tod
+#include <occ_common.h> // For GPE_BUFFER
+#include <occ_service_codes.h> // For OCC reason codes
+#include <sensor_service_codes.h> // For GET_TOD_*_MOD module ids
+#include <trac.h> // For trace macros
+#include <errl.h> // For error logging functions and types
+#include <occhw_async.h> // For gpe_request_*(), async_request_is_idle()
+#include <get_tod_structs.h> // For gpe_get_tod_args_t and TOD_VALUE_UNKNOWN
+#include <occ_sys_config.h> // For G_sysConfigData
+
+
+//******************************************************************************
+// Defines
+//******************************************************************************
+
+/**
+ * Number of errors before we trace.
+ */
+#define GET_TOD_ERRORS_BEFORE_TRACE 1
+
+/**
+ * Number of errors before we set G_tod to TOD_VALUE_UNKNOWN.
+ */
+#define GET_TOD_ERRORS_BEFORE_UNKNOWN 4
+
+/**
+ * Number of errors before we log the error.
+ */
+#define GET_TOD_ERRORS_BEFORE_LOG 16
+
+/**
+ * Maximum number of errors to count. Must fit in a uint8_t.
+ */
+#define GET_TOD_MAX_ERRORS GET_TOD_ERRORS_BEFORE_LOG
+
+
+//******************************************************************************
+// Structs and Enums
+//******************************************************************************
+
+/**
+ * Type of data to store in the user details section of an error log.
+ */
+typedef enum
+{
+ GET_TOD_ERRL_USR_DTLS_NONE, ///< No data to store
+ GET_TOD_ERRL_USR_DTLS_GPE_FFDC ///< ffdc value from GPE0 in G_get_tod_args
+} GET_TOD_ERRL_USR_DTLS_DATA;
+
+
+//******************************************************************************
+// Globals
+//******************************************************************************
+
+/**
+ * Buffer holding arguments for the IPC function. Used to pass data to/from GPE0.
+ */
+GPE_BUFFER(gpe_get_tod_args_t G_get_tod_args);
+
+/**
+ * GPE request structure. Used by GPE functions to schedule request.
+ */
+GpeRequest G_get_tod_request;
+
+/**
+ * Specifies whether the GPE request was scheduled. If false, the request
+ * finished or has never been scheduled/initialized.
+ */
+bool G_get_tod_req_scheduled = false;
+
+/**
+ * Specifies whether the results of the GPE request are available. Must be
+ * declared volatile since it is used by both regular and callback functions.
+ */
+volatile bool G_get_tod_results_available = false;
+
+/**
+ * Number of consecutive errors that have occurred. Cleared when we
+ * successfully obtain the current time of day.
+ */
+uint8_t G_get_tod_error_count = 0;
+
+/**
+ * Specifies whether this task is enabled. If the task is disabled it will no
+ * longer attempt to get the current time of day.
+ */
+bool G_get_tod_enabled = true;
+
+
+//******************************************************************************
+// Private Functions
+//******************************************************************************
+
+/**
+ * Increment the error count.
+ */
+void get_tod_increment_error_count()
+{
+ // Increment error count if we are below the maximum
+ if (G_get_tod_error_count < GET_TOD_MAX_ERRORS)
+ {
+ ++G_get_tod_error_count;
+ }
+
+ // Set time of day to unknown if needed
+ if (G_get_tod_error_count == GET_TOD_ERRORS_BEFORE_UNKNOWN)
+ {
+ G_tod = TOD_VALUE_UNKNOWN;
+ }
+}
+
+
+/**
+ * Clear the error count.
+ *
+ * If there had previously been errors, trace that we have recovered.
+ */
+void get_tod_clear_error_count()
+{
+ // If one or more errors had occurred
+ if (G_get_tod_error_count > 0)
+ {
+ // Trace that we recovered
+ TRAC_INFO("get_tod_clear_error_count: Task recovered after %u errors",
+ G_get_tod_error_count);
+
+ // Clear error count
+ G_get_tod_error_count = 0;
+ }
+}
+
+
+/**
+ * Logs and commits an unrecoverable error. Calls out the processor. Creates a
+ * user details section if needed containing the specified additional data.
+ * Does nothing if an error has already been logged.
+ *
+ * Disables this task. We will no longer try to read the current time of day.
+ *
+ * Note that the required error log comment containing tags like 'userdata4' and
+ * 'devdesc' must be located by the call to this function. It is not located
+ * inside this function because the value of those tags varies.
+ *
+ * @param i_modId Module ID
+ * @param i_reasonCode Reason code
+ * @param i_extReasonCode Extended reason code
+ * @param i_userData1 Userdata1 value
+ * @param i_userData2 Userdata2 value
+ * @param i_usrDtlsData Data to store in a user details section (if any)
+ */
+void get_tod_log_error(uint16_t i_modId, uint8_t i_reasonCode,
+ uint16_t i_extReasonCode, uint32_t i_userData1,
+ uint32_t i_userData2, GET_TOD_ERRL_USR_DTLS_DATA i_usrDtlsData)
+{
+ // Exit if we have already logged an error
+ static bool L_error_logged = false;
+ if (L_error_logged)
+ {
+ return;
+ }
+
+ // Create unrecoverable error
+ errlHndl_t l_errl = createErrl(i_modId, // Module ID
+ i_reasonCode, // Reason code
+ i_extReasonCode, // Extended reason code
+ ERRL_SEV_UNRECOVERABLE, // Severity
+ NULL, // Trace Buffers
+ DEFAULT_TRACE_SIZE, // Trace Size
+ i_userData1, // Userdata1
+ i_userData2); // Userdata2
+
+ // If specified, add user details section to hold ffdc field from GPE
+ if (i_usrDtlsData == GET_TOD_ERRL_USR_DTLS_GPE_FFDC)
+ {
+ addUsrDtlsToErrl(l_errl,
+ (uint8_t *) &(G_get_tod_args.error.ffdc),
+ sizeof(G_get_tod_args.error.ffdc),
+ ERRL_USR_DTL_STRUCT_VERSION_1,
+ ERRL_USR_DTL_BINARY_DATA);
+ }
+
+ // Add processor callout
+ addCalloutToErrl(l_errl,
+ ERRL_CALLOUT_TYPE_HUID,
+ G_sysConfigData.proc_huid,
+ ERRL_CALLOUT_PRIORITY_MED);
+
+ // Commit error
+ commitErrl(&l_errl);
+ L_error_logged = true;
+
+ // Disable this task
+ TRAC_ERR("get_tod_log_error: Disabled task due to logging an error");
+ G_get_tod_enabled = false;
+}
+
+
+/**
+ * Returns whether the global GPE request struct is idle and ready for re-use.
+ * Returns true immediately if the request was not scheduled. If the request
+ * was scheduled, checks to see if it has finished.
+ *
+ * @return true if GPE request is idle, false otherwise
+ */
+bool get_tod_is_request_idle(void)
+{
+ // If the request was not previously scheduled, then it is idle. This also
+ // handles the case where the request has not been initialized yet.
+ if (!G_get_tod_req_scheduled)
+ {
+ return true;
+ }
+
+ // Request was scheduled; check if it finished and is now idle
+ if (async_request_is_idle(&G_get_tod_request.request))
+ {
+ // Request is now idle and ready for re-use
+ G_get_tod_req_scheduled = false;
+ return true;
+ }
+
+ // Request was scheduled but has not finished. Increment error count.
+ get_tod_increment_error_count();
+
+ // Trace if necessary
+ if (G_get_tod_error_count == GET_TOD_ERRORS_BEFORE_TRACE)
+ {
+ TRAC_ERR("get_tod_is_request_idle: Waiting for request to finish");
+ }
+
+ // Log error if necessary
+ if (G_get_tod_error_count == GET_TOD_ERRORS_BEFORE_LOG)
+ {
+ /* @
+ * @errortype
+ * @moduleid GET_TOD_IS_REQ_IDLE_MOD
+ * @reasoncode GPE_REQUEST_TASK_NOT_IDLE
+ * @userdata1 0
+ * @userdata2 0
+ * @userdata4 ERC_GENERIC_TIMEOUT
+ * @devdesc GPE request not finished after waiting repeatedly
+ */
+ get_tod_log_error(GET_TOD_IS_REQ_IDLE_MOD, GPE_REQUEST_TASK_NOT_IDLE,
+ ERC_GENERIC_TIMEOUT, 0, 0, GET_TOD_ERRL_USR_DTLS_NONE);
+ }
+
+ // Return false since request is not idle
+ return false;
+}
+
+
+/**
+ * Callback that is invoked when the GPE request completes.
+ *
+ * @param i_arg Callback argument specified during gpe_request_create(). Not used.
+ */
+int get_tod_callback(void * i_arg)
+{
+ // NOTE: No tracing allowed in callback functions
+
+ // If GPE request was successful copy current time of day into G_tod. We do
+ // this in a callback so G_tod is updated as soon as possible.
+ if (G_get_tod_args.error.rc == GPE_RC_SUCCESS)
+ {
+ G_tod = G_get_tod_args.tod;
+ }
+
+ // Set flag indicating results of GPE request are available. Any errors
+ // will be handled later since callbacks cannot trace.
+ G_get_tod_results_available = true;
+
+ // Return 0 indicating to async framework that callback ran successfully
+ return 0;
+}
+
+
+/**
+ * Handles the results of the previous GPE request.
+ */
+void get_tod_handle_request_results(void)
+{
+ // Check if results from previous GPE request are available
+ if (!G_get_tod_results_available)
+ {
+ // No results available, so there is nothing to do. There was no
+ // previous request, or previous request didn't complete due to errors.
+ return;
+ }
+
+ // Check whether GPE request successfully read time of day
+ if (G_get_tod_args.error.rc == GPE_RC_SUCCESS)
+ {
+ // Request succeeded. Callback already set G_tod. Clear error counter.
+ get_tod_clear_error_count();
+ }
+ else
+ {
+ // Request failed to read time of day; increment error count
+ get_tod_increment_error_count();
+
+ // Trace if needed
+ if (G_get_tod_error_count == GET_TOD_ERRORS_BEFORE_TRACE)
+ {
+ TRAC_ERR("get_tod_handle_request_results: GPE0 error reading TOD register: "
+ "addr=0x%08X, rc=0x%08X, ffdc=0x%08X%08X",
+ G_get_tod_args.error.addr,
+ G_get_tod_args.error.rc,
+ (uint32_t) (G_get_tod_args.error.ffdc >> 32),
+ (uint32_t) (G_get_tod_args.error.ffdc & 0x00000000FFFFFFFFull));
+ }
+
+ // Log error if needed
+ if (G_get_tod_error_count == GET_TOD_ERRORS_BEFORE_LOG)
+ {
+ /* @
+ * @errortype
+ * @moduleid GET_TOD_HNDL_REQ_RSLT_MOD
+ * @reasoncode GPE_REQUEST_RC_FAILURE
+ * @userdata1 SCOM address
+ * @userdata2 RC from GPE IPC function
+ * @userdata4 ERC_GETSCOM_FAILURE
+ * @devdesc GPE request to read SCOM TOD register failed
+ */
+ get_tod_log_error(GET_TOD_HNDL_REQ_RSLT_MOD, GPE_REQUEST_RC_FAILURE,
+ ERC_GETSCOM_FAILURE, G_get_tod_args.error.addr,
+ G_get_tod_args.error.rc, GET_TOD_ERRL_USR_DTLS_GPE_FFDC);
+ }
+ }
+
+ // Clear flag since we handled the results of the previous GPE request
+ G_get_tod_results_available = false;
+}
+
+
+/**
+ * Schedules a GPE request to read the TOD register to get current time of day.
+ */
+void get_tod_schedule_request(void)
+{
+ // Create (initialize) GPE request if needed
+ static bool L_request_created = false;
+ if (!L_request_created)
+ {
+ int l_rc = gpe_request_create(&G_get_tod_request, // GpeRequest
+ &G_async_gpe_queue0, // Queue for GPE0
+ IPC_ST_GET_TOD_FUNCID, // IPC Function ID
+ &G_get_tod_args, // IPC Command Data
+ SSX_WAIT_FOREVER, // Timeout (none)
+ get_tod_callback, // Callback
+ NULL, // Callback argument
+ ASYNC_CALLBACK_IMMEDIATE); // Options
+ if (l_rc != 0)
+ {
+ // Create failed; trace and log error, then exit. Ignore error
+ // count because we don't retry creates.
+ TRAC_ERR("get_tod_schedule_request: Request create failure: rc=0x%08X", l_rc);
+ /* @
+ * @errortype
+ * @moduleid GET_TOD_SCHED_REQ_MOD
+ * @reasoncode GPE_REQUEST_CREATE_FAILURE
+ * @userdata1 Return code from gpe_request_create()
+ * @userdata2 0
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc Failed to create GPE request
+ */
+ get_tod_log_error(GET_TOD_SCHED_REQ_MOD, GPE_REQUEST_CREATE_FAILURE,
+ OCC_NO_EXTENDED_RC, l_rc, 0, GET_TOD_ERRL_USR_DTLS_NONE);
+ return;
+ }
+ L_request_created = true;
+ }
+
+ // Schedule GPE request
+ int l_rc = gpe_request_schedule(&G_get_tod_request);
+ if (l_rc != 0)
+ {
+ // Schedule failed; increment error count
+ get_tod_increment_error_count();
+
+ // Trace if needed
+ if (G_get_tod_error_count == GET_TOD_ERRORS_BEFORE_TRACE)
+ {
+ TRAC_ERR("get_tod_schedule_request: Request schedule failure: rc=0x%08X", l_rc);
+ }
+
+ // Log error if needed
+ if (G_get_tod_error_count == GET_TOD_ERRORS_BEFORE_LOG)
+ {
+ /* @
+ * @errortype
+ * @moduleid GET_TOD_SCHED_REQ_MOD
+ * @reasoncode GPE_REQUEST_SCHEDULE_FAILURE
+ * @userdata1 Return code from gpe_request_schedule()
+ * @userdata2 0
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc Failed to schedule GPE request
+ */
+ get_tod_log_error(GET_TOD_SCHED_REQ_MOD, GPE_REQUEST_SCHEDULE_FAILURE,
+ OCC_NO_EXTENDED_RC, l_rc, 0, GET_TOD_ERRL_USR_DTLS_NONE);
+ }
+ return;
+ }
+
+ // Successfully scheduled request. Request is not blocking, so we will not
+ // get the results until later. Set flag indicating request is scheduled.
+ G_get_tod_req_scheduled = true;
+}
+
+
+//******************************************************************************
+// Public Functions
+//******************************************************************************
+
+// See description in header file
+void task_get_tod(task_t * i_self)
+{
+ // Exit if this task is disabled
+ if (!G_get_tod_enabled)
+ {
+ return;
+ }
+
+ // Exit if the previous GPE request has not finished
+ if (!get_tod_is_request_idle())
+ {
+ return;
+ }
+
+ // Handle results of previous GPE request
+ get_tod_handle_request_results();
+ if (!G_get_tod_enabled)
+ {
+ // Task disabled due to errors while handling request results
+ return;
+ }
+
+ // Schedule new GPE request to get time of day
+ get_tod_schedule_request();
+}
diff --git a/src/occ_405/sensor/sensor_get_tod_task.h b/src/occ_405/sensor/sensor_get_tod_task.h
new file mode 100644
index 0000000..d46da75
--- /dev/null
+++ b/src/occ_405/sensor/sensor_get_tod_task.h
@@ -0,0 +1,54 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/occ_405/sensor/sensor_get_tod_task.h $ */
+/* */
+/* OpenPOWER OnChipController Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2017,2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* 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 _SENSOR_GET_TOD_TASK_H
+#define _SENSOR_GET_TOD_TASK_H
+
+/**
+ * @file sensor_get_tod_task.h
+ *
+ * This file declares the functions for the task that gets the current Time Of
+ * Day (TOD).
+ */
+
+//******************************************************************************
+// Includes
+//******************************************************************************
+#include <rtls.h> // For task_t
+
+
+//******************************************************************************
+// Function Prototypes
+//******************************************************************************
+
+/**
+ * Initial function called by the TASK_ID_GET_TOD task. Gets the current Time
+ * Of Day (TOD) value and stores it in the global variable G_tod.
+ *
+ * @param i_self This task
+ */
+void task_get_tod(task_t * i_self);
+
+#endif // _SENSOR_GET_TOD_TASK_H
diff --git a/src/occ_405/sensor/sensor_main_memory.c b/src/occ_405/sensor/sensor_main_memory.c
index 66e4da8..7e4cb51 100644
--- a/src/occ_405/sensor/sensor_main_memory.c
+++ b/src/occ_405/sensor/sensor_main_memory.c
@@ -43,6 +43,7 @@
#include <occ_service_codes.h> // For OCC reason codes
#include <sensor_service_codes.h> // For sensor module ids
#include <trac.h> // For trace macros
+#include <errl.h> // For error logging functions and types
#include <occhw_async.h> // For bce_request_*(), async_request_is_idle()
#include <cmdh_fsp_cmds.h> // For G_apss_ch_to_function
diff --git a/src/occ_405/sensor/sensor_service_codes.h b/src/occ_405/sensor/sensor_service_codes.h
index f511edf..35e2045 100755
--- a/src/occ_405/sensor/sensor_service_codes.h
+++ b/src/occ_405/sensor/sensor_service_codes.h
@@ -50,6 +50,11 @@ enum occSensorModuleId
INBAND_CMD_BCE_COPY_MOD = SNSR_COMP_ID | 0x21,
INBAND_CMD_HANDLER_MOD = SNSR_COMP_ID | 0x22,
INBAND_CMD_CHECK_MOD = SNSR_COMP_ID | 0x23,
+
+ // Get time of day task
+ GET_TOD_IS_REQ_IDLE_MOD = SNSR_COMP_ID | 0x30,
+ GET_TOD_HNDL_REQ_RSLT_MOD = SNSR_COMP_ID | 0x31,
+ GET_TOD_SCHED_REQ_MOD = SNSR_COMP_ID | 0x32,
};
#endif /* #ifndef _SENSOR_SERVICE_CODES_H_ */
diff --git a/src/occ_405/topfiles.mk b/src/occ_405/topfiles.mk
index f3b85ad..faae172 100644
--- a/src/occ_405/topfiles.mk
+++ b/src/occ_405/topfiles.mk
@@ -84,6 +84,7 @@ TOP-C-SOURCES = amec/amec_analytics.c \
rtls/rtls_tables.c \
rtls/rtls.c \
scom.c \
+ sensor/sensor_get_tod_task.c \
sensor/sensor_inband_cmd.c \
sensor/sensor_info.c \
sensor/sensor_main_memory.c \
diff --git a/src/occ_gpe0/gpe_get_tod.c b/src/occ_gpe0/gpe_get_tod.c
new file mode 100644
index 0000000..187a61b
--- /dev/null
+++ b/src/occ_gpe0/gpe_get_tod.c
@@ -0,0 +1,154 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/occ_gpe0/gpe_get_tod.c $ */
+/* */
+/* OpenPOWER OnChipController Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2017,2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* 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 */
+
+/**
+ * @file gpe_get_tod.c
+ *
+ * This file defines the functions for getting the current value of the Time Of
+ * Day (TOD) register.
+ */
+
+//******************************************************************************
+// Includes
+//******************************************************************************
+
+#include <stdint.h> // For uint*_t
+#include "pk.h" // For PK_TRACE() and pk_halt()
+#include "ipc_api.h" // For ipc_msg_t
+#include "ipc_async_cmd.h" // For ipc_async_cmd_t
+#include "ppe42_scom.h" // For getscom_abs()
+#include "gpe_util.h" // For gpe_set_ffdc()
+#include "get_tod_structs.h" // For gpe_get_tod_args_t
+#include "gpe_err.h" // For GPE_RC_*
+#include "pss_constants.h" // For TOD_STATUS_REG and TOD_VALUE_REG
+
+
+//******************************************************************************
+// Defines
+//******************************************************************************
+
+/**
+ * Returns the IS_RUNNING bit within the TOD_STATUS_REG register.
+ *
+ * IS_RUNNING is bit 20 in the register value. Note that bit 0 is the most
+ * significant bit.
+ *
+ * @param reg_value value of TOD_STATUS_REG register
+ * @return IS_RUNNING bit. If 1, the TOD is running.
+ */
+#define TOD_IS_RUNNING(reg_value) \
+ (((uint8_t) (((uint64_t) (reg_value)) >> 43)) & 0x01u)
+
+/**
+ * Returns the TOD_VALUE field within the TOD_VALUE_REG register.
+ *
+ * The TOD_VALUE field is located in bits 0:59 of the register value. Note that
+ * bit 0 is the most significant bit. In the returned value we must set the low
+ * order 4 bits (60:63) to 0 rather than right shifting 4 bits.
+ *
+ * @param reg_value value of TOD_VALUE_REG register
+ * @return TOD_VALUE field
+ */
+#define TOD_VALUE(reg_value) (((uint64_t) (reg_value)) & 0xFFFFFFFFFFFFFFF0ull)
+
+
+//******************************************************************************
+// Functions
+//******************************************************************************
+
+/**
+ * Reads the value of the TOD_STATUS_REG and TOD_VALUE_REG registers. If the
+ * TOD is running, the current Time Of Day value is stored in the tod field of
+ * the args parameter.
+ *
+ * @param args Arguments passed from the OCC 405 via the IPC framework
+ */
+void gpe_read_tod_registers(gpe_get_tod_args_t * args)
+{
+ // Initialize output arguments to default values
+ args->error.rc = GPE_RC_SUCCESS;
+ args->error.addr = 0;
+ args->error.ffdc = 0;
+ args->tod = TOD_VALUE_UNKNOWN;
+
+ // Read value of TOD_STATUS_REG register
+ uint64_t l_reg_val;
+ uint32_t rc = getscom_abs(TOD_STATUS_REG, &l_reg_val);
+ if (rc != 0)
+ {
+ gpe_set_ffdc(&(args->error), TOD_STATUS_REG, GPE_RC_SCOM_GET_FAILED, rc);
+ return;
+ }
+
+ // Check if TOD is running based on TOD_STATUS_REG value.
+ if (!TOD_IS_RUNNING(l_reg_val))
+ {
+ // TOD is not running. Operating system is likely fixing it. Not an error.
+ return;
+ }
+
+ // Read value of TOD_VALUE_REG register
+ rc = getscom_abs(TOD_VALUE_REG, &l_reg_val);
+ if (rc != 0)
+ {
+ gpe_set_ffdc(&(args->error), TOD_VALUE_REG, GPE_RC_SCOM_GET_FAILED, rc);
+ return;
+ }
+
+ // The TOD_VALUE_REG register contains two fields. Get the TOD_VALUE field
+ // and store that as the Time Of Day value.
+ args->tod = TOD_VALUE(l_reg_val);
+}
+
+
+/**
+ * IPC function that gets the current Time Of Day (TOD) value.
+ *
+ * First reads the TOD_STATUS_REG register to make sure the TOD is running.
+ * Then reads the TOD_VALUE_REG register to get the TOD value.
+ *
+ * @param cmd A pointer to the IPC command message
+ * @param arg IPC function argument. Currently not used.
+ */
+void gpe_get_tod(ipc_msg_t * cmd, void * arg)
+{
+ // Cast command message pointer to more specific type to access cmd_data field
+ ipc_async_cmd_t * async_cmd = (ipc_async_cmd_t *) cmd;
+
+ // Cast cmd_data field to specific type of arguments for this IPC function
+ gpe_get_tod_args_t * args = (gpe_get_tod_args_t *) async_cmd->cmd_data;
+
+ // Read the TOD registers to get the TOD value. Store the result in args.
+ gpe_read_tod_registers(args);
+
+ // Send back a response with IPC success even if ffdc/rc fields are non-zero
+ int rc = ipc_send_rsp(cmd, IPC_RC_SUCCESS);
+ if (rc != 0)
+ {
+ PK_TRACE("gpe_get_tod: Failed to send response back. Halting GPE0. rc=0x%08X", rc);
+ gpe_set_ffdc(&(args->error), 0x00, GPE_RC_IPC_SEND_FAILED, rc);
+ pk_halt();
+ }
+}
diff --git a/src/occ_gpe0/ipc_func_tables.c b/src/occ_gpe0/ipc_func_tables.c
index 91644c5..14166df 100644
--- a/src/occ_gpe0/ipc_func_tables.c
+++ b/src/occ_gpe0/ipc_func_tables.c
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER OnChipController Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2015,2016 */
+/* Contributors Listed Below - COPYRIGHT 2015,2017 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -34,6 +34,7 @@ void apss_continue_pwr_meas_read(ipc_msg_t* cmd, void* arg);
void apss_complete_pwr_meas_read(ipc_msg_t* cmd, void* arg);
void gpe_get_core_data(ipc_msg_t* cmd, void* arg);
void gpe_get_nest_dts(ipc_msg_t* cmd, void* arg);
+void gpe_get_tod(ipc_msg_t* cmd, void* arg);
void ipc_scom_operation(ipc_msg_t* cmd, void* arg);
void ipc_fir_collection(ipc_msg_t* cmd, void* arg);
@@ -73,7 +74,7 @@ IPC_HANDLER(ipc_scom_operation, 0) // 7 - IPC_ST_SCOM_OPERATION
IPC_HANDLER(gpe0_nop, 0) // 8 - IPC_ST_GPE0_NOP
IPC_HANDLER(gpe_get_nest_dts, 0) // 9 - IPC_ST_GET_NEST_DTS_FUNCID
IPC_HANDLER(ipc_fir_collection, 0) // 10 - IPC_ST_FIR_COLLECTION
-IPC_HANDLER_DEFAULT // 11
+IPC_HANDLER(gpe_get_tod, 0) // 11 - IPC_ST_GET_TOD_FUNCID
IPC_HANDLER_DEFAULT // 12
IPC_HANDLER_DEFAULT // 13
IPC_HANDLER_DEFAULT // 14
diff --git a/src/occ_gpe0/topfiles.mk b/src/occ_gpe0/topfiles.mk
index 682e2d6..332a2c3 100644
--- a/src/occ_gpe0/topfiles.mk
+++ b/src/occ_gpe0/topfiles.mk
@@ -5,7 +5,7 @@
#
# OpenPOWER OnChipController Project
#
-# Contributors Listed Below - COPYRIGHT 2015,2016
+# Contributors Listed Below - COPYRIGHT 2015,2017
# [+] International Business Machines Corp.
#
#
@@ -24,7 +24,8 @@
# IBM_PROLOG_END_TAG
FIRDATA_SOURCES = $(wildcard firdata/*.c)
TOP-C-SOURCES = gpe0_main.c pk_app_irq_table.c ipc_func_tables.c apss_read.c \
- apss_init.c gpe_util.c core_data.c gpe_core_data.c nest_dts.c ${FIRDATA_SOURCES}
+ apss_init.c gpe_util.c core_data.c gpe_core_data.c nest_dts.c ${FIRDATA_SOURCES} \
+ gpe_get_tod.c
TOP-S-SOURCES =
TOP_OBJECTS = $(TOP-C-SOURCES:.c=.o) $(TOP-S-SOURCES:.S=.o)
OpenPOWER on IntegriCloud