summaryrefslogtreecommitdiffstats
path: root/src/occ_gpe0/gpe_get_tod.c
blob: 187a61b7453d14548b02f6451612f089e89c01df (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
/* 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();
    }
}
OpenPOWER on IntegriCloud