summaryrefslogtreecommitdiffstats
path: root/src/import/chips/p9/procedures/hwp/memory/p9_mss_draminit_mc.C
blob: 8555d5f00f3f99a59ba00d8447eede9a6555e87f (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
/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: chips/p9/procedures/hwp/memory/p9_mss_draminit_mc.C $         */
/*                                                                        */
/* IBM CONFIDENTIAL                                                       */
/*                                                                        */
/* EKB Project                                                            */
/*                                                                        */
/* COPYRIGHT 2015,2016                                                    */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* The source code for this program is not published or otherwise         */
/* divested of its trade secrets, irrespective of what has been           */
/* deposited with the U.S. Copyright Office.                              */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

///
/// @file p9_mss_draminit_mc.C
/// @brief Initialize the memory controller to take over the DRAM
///
// *HWP HWP Owner: Brian Silver <bsilver@us.ibm.com>
// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 2
// *HWP Consumed by: FSP:HB

#include <fapi2.H>
#include <mss.H>

#include <p9_mss_draminit_mc.H>

using fapi2::TARGET_TYPE_MCBIST;
using fapi2::TARGET_TYPE_MCA;
using fapi2::TARGET_TYPE_MCS;

extern "C"
{
///
/// @brief Initialize the MC now that DRAM is up
/// @param[in] i_target, the McBIST of the ports
/// @return FAPI2_RC_SUCCESS iff ok
///
    fapi2::ReturnCode p9_mss_draminit_mc( const fapi2::Target<TARGET_TYPE_MCBIST>& i_target )
    {
        auto l_mca = i_target.getChildren<TARGET_TYPE_MCA>();

        FAPI_INF("Start draminit MC");

        // If we don't have any ports, lets go.
        if (l_mca.size() == 0)
        {
            FAPI_INF("No ports? %s", mss::c_str(i_target));
            return fapi2::FAPI2_RC_SUCCESS;
        }

        // While we're doing the scominit in here, lets do it for all ports before we dump the MCS regs.
        for (auto p : i_target.getChildren<TARGET_TYPE_MCA>())
        {
            mss::mc<TARGET_TYPE_MCS> l_mc;

            // Don't do this yet - leverage the sim inits for the moment
#if 0
            // All the scominit for this MCA
            l_mc.scominit(p);
#endif
            // Setup the MC port/dimm address translation registers
            FAPI_TRY( l_mc.setup_xlate_map(p) );
        }

        for (auto p : l_mca)
        {

            // Setup the read_pointer_delay
            // TK: Do we need to do this in general or is this a place holder until the
            // init file gets here?
            {
                fapi2::buffer<uint64_t> l_data;
                FAPI_TRY( mss::getScom(p, MCA_RECR, l_data) );
                l_data.insertFromRight<MCA_RECR_MBSECCQ_READ_POINTER_DELAY, MCA_RECR_MBSECCQ_READ_POINTER_DELAY_LEN>(0x1);
                FAPI_DBG("writing read pointer delay 0x%016lx %s", l_data, mss::c_str(p));
                FAPI_TRY( mss::putScom(p, MCA_RECR, l_data) );
            }

            // Set the IML Complete bit MBSSQ(3) (SCOM Addr: 0x02011417) to indicate that IML has completed
            // Can't find MBSSQ or the iml_complete bit - asked Steve. Gary VH created this bit as a scratch
            // 'you are hre bit' and it was removed for Nimbus. Gary VH asked for it to be put back in. Not
            // sure if that happened yet. BRS (2/16).

            // Reset addr_mux_sel to “0” to allow the MCA to take control of the DDR interface over from CCS.
            // (Note: this step must remain in this procedure to ensure that data path is placed into mainline
            // mode prior to running memory diagnostics. This step maybe superfluous but not harmful.)
            // Note: addr_mux_sel is set low in p9_mss_draminit(), however that might be a work-around so we
            // set it low here kind of like belt-and-suspenders. BRS
            FAPI_TRY( mss::change_addr_mux_sel(p, mss::LOW) );

            // Re-enable port fails. Turned off in draminit_training
            FAPI_TRY( mss::change_port_fail_disable(p, mss::OFF ) );

            // Step Two.1: Check RCD protect time on RDIMM and LRDIMM
            // Step Two.2: Enable address inversion on each MBA for ALL CARDS

            // Start the refresh engines by setting MBAREF0Q(0) = “1”. Note that the remaining bits in
            // MBAREF0Q should retain their initialization values.
            FAPI_TRY( mss::change_refresh_enable(p, mss::HIGH) );

            // Power management is handled in the init file. (or should be BRS)

            // Enabling periodic calibration
            FAPI_TRY( mss::enable_periodic_cal(p) );

            // Step Six: Setup Control Bit ECC
            FAPI_TRY( mss::enable_read_ecc(p) );

            // At this point the DDR interface must be monitored for memory errors. Memory related FIRs should be unmasked.

            // Cram a fast write, followed by a read in here for giggles
            {
                mss::mcbist::program<TARGET_TYPE_MCBIST> l_program;
                uint64_t l_start = 0;
                uint64_t l_end = 0;
                uint64_t l_pattern = 0;

                // Write
                {
                    // Uses address register set 0
                    mss::mcbist::subtest_t<TARGET_TYPE_MCBIST> l_fw_subtest =
                        mss::mcbist::write_subtest<TARGET_TYPE_MCBIST>();
                    l_fw_subtest.enable_port(mss::relative_pos<TARGET_TYPE_MCBIST>(p));

                    // Run in ECC mode

                    // HACK: We only need to worry about the DIMM in slot 0 right now
                    l_fw_subtest.enable_dimm(0);
                    l_program.iv_subtests.push_back(l_fw_subtest);
                }

                // Read
                {
                    // Uses address register set 0
                    mss::mcbist::subtest_t<TARGET_TYPE_MCBIST> l_fr_subtest =
                        mss::mcbist::read_subtest<TARGET_TYPE_MCBIST>();
                    l_fr_subtest.enable_port(mss::relative_pos<TARGET_TYPE_MCBIST>(p));

                    // Run in ECC mode

                    // HACK: We only need to worry about the DIMM in slot 0 right now
                    l_fr_subtest.enable_dimm(0);
                    l_program.iv_subtests.push_back(l_fr_subtest);
                }

                FAPI_TRY( mss::mcbist_start_addr(p, l_start) );
                FAPI_TRY( mss::mcbist_end_addr(p, l_end) );

                // TK: calculate proper polling based on address range

                // Setup a nice pattern for writing
                FAPI_TRY( mss::mcbist_write_data(i_target, l_pattern) );
                FAPI_TRY( mss::putScom(i_target, MCBIST_MCBFD0Q, l_pattern) );
                FAPI_TRY( mss::putScom(i_target, MCBIST_MCBFD1Q, l_pattern) );
                FAPI_TRY( mss::putScom(i_target, MCBIST_MCBFD2Q, l_pattern) );
                FAPI_TRY( mss::putScom(i_target, MCBIST_MCBFD3Q, l_pattern) );
                FAPI_TRY( mss::putScom(i_target, MCBIST_MCBFD4Q, l_pattern) );
                FAPI_TRY( mss::putScom(i_target, MCBIST_MCBFD5Q, l_pattern) );
                FAPI_TRY( mss::putScom(i_target, MCBIST_MCBFD6Q, l_pattern) );
                FAPI_TRY( mss::putScom(i_target, MCBIST_MCBFD7Q, l_pattern) );

                // Sanity check - can't do much if end is before start.
                // This is either a programming error or a mistake in attribute settings. So we'll just assert.
                if (l_end < l_start)
                {
                    FAPI_ERR("mcbist end address is less than mcbist starting address. s: 0x%x e: 0x%x", l_start, l_end);
                    fapi2::Assert(false);
                }

                // By default we're in maint address mode so we do a start + len and the 'BIST increments for us.
                // By default, the write subtest uses the 0'th address start/end registers.
                mss::mcbist::config_address_range0(i_target, l_start, l_end - l_start);

                // Setup the polling based on a heuristic <cough>guess</cough>
                // Looks like 20ns per address for a write/read program, and add a long number of polls
                l_program.iv_poll.iv_initial_delay = (l_end - l_start) * 2 * mss::DELAY_10NS;
                l_program.iv_poll.iv_initial_sim_delay =
                    mss::cycles_to_simcycles(mss::ns_to_cycles(i_target, l_program.iv_poll.iv_initial_delay));
                l_program.iv_poll.iv_poll_count = 100;

                // Just one port for now. Per Shelton we need to set this in maint adress mode
                // even tho we specify the port/dimm in the subtest.
                fapi2::buffer<uint8_t> l_port;
                l_port.setBit(mss::relative_pos<TARGET_TYPE_MCBIST>(p));
                l_program.select_ports(l_port >> 4);

                // Kick it off, wait for a result
                FAPI_TRY( mss::mcbist::execute(i_target, l_program) );
            }
        }

    fapi_try_exit:
        FAPI_INF("End draminit MC");
        return fapi2::current_err;
    }
}
OpenPOWER on IntegriCloud