summaryrefslogtreecommitdiffstats
path: root/src/import/chips/p9/procedures/hwp/nest/p9_l3_flush.C
blob: 6a9346f3dade7e874dabd3abcd1ed424f1cbebf8 (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
/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/nest/p9_l3_flush.C $       */
/*                                                                        */
/* OpenPOWER sbe Project                                                  */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,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 p9_l3_flush.C
/// @brief Initiates an L3 purge request
///
/// *HWP HWP Owner: Benjamin Gass <bgass@us.ibm.com>
/// *HWP FW Owner: Thi Tran thi@us.ibm.com
/// *HWP Team: Nest
/// *HWP Level: 3
/// *HWP Consumed by: FSP and SBE
/// ----------------------------------------------------------------------------

//--------------------------------------------------------------------------
// Includes
//--------------------------------------------------------------------------
#include <p9_l3_flush.H>
#include <p9_quad_scom_addresses.H>
#include <p9_quad_scom_addresses_fld.H>

//--------------------------------------------------------------------------
// Constant definitions
//--------------------------------------------------------------------------

// L3 purge operation delay times for HW/sim
const uint32_t P9_L3_FLUSH_HW_NS_DELAY     = 50000;
const uint32_t P9_L3_FLUSH_SIM_CYCLE_DELAY = 1000000;

// If the L3 purge is not completed in P9_L3_FLUSH_TIMEOUT delays, fail with error
const uint32_t P9_L3_FLUSH_TIMEOUT_COUNT = 40;

//--------------------------------------------------------------------------
//  HWP entry point
//--------------------------------------------------------------------------

// TODO: RTC 177535 - Do we support SINGLE_PURGE/DELETE?
fapi2::ReturnCode p9_l3_flush(
    const fapi2::Target<fapi2::TARGET_TYPE_EX>& i_target,
    const uint32_t i_purge_type,
    const uint32_t i_purge_addr)
{
    // mark HWP entry
    FAPI_DBG("Entering ...\n");

    fapi2::buffer<uint64_t> purge_reg_data(0x0);
    uint32_t purge_pending_count = 0;

    //Make sure that the inputs are acceptable
    //Make sure the purge type is full purge, single purge, single delete, full blind, or dynamic
    //Make sure that the purge address fits withing bits 17:28
    FAPI_ASSERT(!((i_purge_type != L3_FULL_PURGE) &&
                  (i_purge_type != L3_SINGLE_PURGE) &&
                  (i_purge_type != L3_FULL_BLIND_PURGE) &&
                  (i_purge_type != L3_DYNAMIC_PURGE)) &&
                (i_purge_addr < 0x1000),
                fapi2::P9_L3_FLUSH_INVALID_ARGS_ERR()
                .set_TARGET(i_target)
                .set_PURGETYPE(i_purge_type)
                .set_PURGEADDR(i_purge_addr),
                "i_purge_type is not a compatible type");

    //Make sure that another flush is not happening
    FAPI_DBG("Verifying that a previous flush is not active");
    FAPI_TRY(fapi2::getScom(i_target, EX_PRD_PURGE_REG, purge_reg_data));
    FAPI_ASSERT(!(purge_reg_data.getBit<EX_PRD_PURGE_REG_L3_REQ>()),
                fapi2::P9_L3_FLUSH_PREVIOUS_PURGE_ACTIVE_ERR()
                .set_TARGET(i_target)
                .set_PURGEREG(purge_reg_data),
                "Previous Purge request has not completed error");

    //Since there is no previous purge, build the purge request

    //Flush the data and set the req bit to initiate the purge
    purge_reg_data.flush<0>().setBit<EX_PRD_PURGE_REG_L3_REQ>();

    //set the type of the purge
    purge_reg_data.insertFromRight<EX_PRD_PURGE_REG_L3_TTYPE,
                                   EX_PRD_PURGE_REG_L3_TTYPE_LEN> (i_purge_type);

    //set the address of where to start for the address
    purge_reg_data.insertFromRight<EX_PRD_PURGE_REG_L3_DIR_ADDR,
                                   EX_PRD_PURGE_REG_L3_DIR_ADDR_LEN> (i_purge_addr);

    //Write the purge request
    FAPI_TRY(fapi2::putScom(i_target, EX_PRD_PURGE_REG, purge_reg_data));

    //Spin on PRD_PURGE_REQ until hardware clears it
    while(purge_pending_count < P9_L3_FLUSH_TIMEOUT_COUNT)
    {
        FAPI_DBG("Waiting for purge to complete...");

        FAPI_TRY(fapi2::delay(P9_L3_FLUSH_HW_NS_DELAY,
                              P9_L3_FLUSH_SIM_CYCLE_DELAY));

        FAPI_TRY(fapi2::getScom(i_target, EX_PRD_PURGE_REG, purge_reg_data));

        if (!purge_reg_data.getBit<EX_PRD_PURGE_REG_L3_REQ>())
        {
            FAPI_DBG("Purge complete!");
            break;
        }

        purge_pending_count++;
    }

    FAPI_ASSERT(purge_pending_count < P9_L3_FLUSH_TIMEOUT_COUNT,
                fapi2::P9_L3_FLUSH_PURGE_REQ_TIMEOUT_ERR()
                .set_TARGET(i_target)
                .set_PURGETYPE(i_purge_type)
                .set_PURGEADDR(i_purge_addr)
                .set_EX_PRD_PURGE_REG_DATA(purge_reg_data),
                "Purge did not complete in time.");

fapi_try_exit:
    FAPI_DBG("Exiting...");
    return fapi2::current_err;
}
OpenPOWER on IntegriCloud