summaryrefslogtreecommitdiffstats
path: root/src/import/chips/p9/procedures/hwp/memory/p9_mss_ddr_phy_reset.C
blob: a7609b3c11a2c41d14aefe42f55410aebed7335c (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
/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: chips/p9/procedures/hwp/memory/p9_mss_ddr_phy_reset.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_ddr_phy_reset.C
/// @brief Reset the DDR PHY
///
// *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 <stdint.h>
#include <string.h>

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

#include <p9_mss_ddr_phy_reset.H>
#include <lib/utils/count_dimm.H>

using fapi2::TARGET_TYPE_MCBIST;

extern "C"
{

///
/// @brief Perform a phy reset on all the PHY related to this half-chip (mcbist)
/// @param[in] the mcbist representing the PHY
/// @return FAPI2_RC_SUCCESS iff OK
///
    fapi2::ReturnCode p9_mss_ddr_phy_reset(const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& i_target)
    {
        FAPI_INF("********* %s start *********", __func__);

        // If there are no DIMM we don't need to bother. In fact, we can't as we didn't setup
        // attributes for the PHY, etc.
        if (mss::count_dimm(i_target) == 0)
        {
            FAPI_INF("... skipping ddr_phy_reset %s - no DIMM ...", mss::c_str(i_target));
            return fapi2::FAPI2_RC_SUCCESS;
        }

        // Initialize via scoms. Could be put in to p9_mss_scominit.C if that ever exists BRS.
        FAPI_TRY( mss::phy_scominit(i_target) );

        FAPI_TRY(mss::change_force_mclk_low(i_target, mss::HIGH),
                 "force_mclk_low (set high) Failed rc = 0x%08X", uint64_t(fapi2::current_err) );

        //
        // 1. Drive all control signals to the PHY to their inactive state, idle state, or inactive value.
        FAPI_TRY( mss::dp16::reset_sysclk(i_target) );

        //    (Note: The chip should already be in this state.)
        FAPI_DBG("All control signals to the PHYs should already be set to their inactive state, idle state, or inactive values");

        // 2. Assert reset to PHY for 32 memory clocks
        FAPI_TRY( mss::change_resetn(i_target, mss::HIGH), "change_resetn for %s failed", mss::c_str(i_target) );
        fapi2::delay(mss::cycles_to_ns(i_target, 32), mss::cycles_to_simcycles(32));

        // 3. Deassert reset_n
        FAPI_TRY( mss::change_resetn(i_target, mss::LOW), "change_resetn for %s failed", mss::c_str(i_target) );

        //
        // Flush output drivers
        //

        // 8. Set FLUSH=1 and INIT_IO=1 in the DDRPHY_ADR_OUTPUT_FORCE_ATEST_CNTL and DDRPHY_DP16_DATA_BIT_DIR1 register
        // 9. Wait at least 32 dphy_gckn clock cycles.
        // 10. Set FLUSH=0 and INIT_IO=0 in the DDRPHY_ADR_OUTPUT_FORCE_ATEST_CNTL register
        FAPI_TRY( mss::flush_output_drivers(i_target), "unable to flush output drivers for %s", mss::c_str(i_target) );

        //
        // ZCTL Enable
        //

        // 11. Assert the ZCNTL enable to the internal impedance controller in DDRPHY_PC_RESETS register
        // 12. Wait at least 1024 dphy_gckn cycles
        // 13. Deassert the ZCNTL impedance controller enable, Check for DONE in DDRPHY_PC_DLL_ZCAL
        FAPI_TRY( mss::enable_zctl(i_target), "enable_zctl for %s failed", mss::c_str(i_target) );

        //
        // DLL calibration
        //

        // 14. Begin DLL calibrations by setting INIT_RXDLL_CAL_RESET=0 in the DDRPHY_DP16_DLL_CNTL{0:1} registers
        // and DDRPHY_ADR_DLL_CNTL registers
        // 15. Monitor the DDRPHY_PC_DLL_ZCAL_CAL_STATUS register to determine when calibration is
        // complete. One of the 3 bits will be asserted for ADR and DP16.
        FAPI_INF( "starting DLL calibration %s", mss::c_str(i_target) );
        FAPI_TRY( mss::dll_calibration(i_target) );

        //
        // Start bang-bang-lock
        //

        // 16. Take dphy_nclk/SysClk alignment circuits out of reset and put into continuous update mode,
        FAPI_INF("set up of phase rotator controls %s", mss::c_str(i_target) );
        FAPI_TRY( mss::setup_phase_rotator_control_registers(i_target, mss::ON) );

        // 17. Wait at least 5932 dphy_nclk clock cycles to allow the dphy_nclk/SysClk alignment circuit to
        // perform initial alignment.
        FAPI_INF("Wait at least 5932 memory clock cycles for clock alignment circuit to perform initial alignment %s",
                 mss::c_str(i_target));
        FAPI_TRY( fapi2::delay(mss::cycles_to_ns(i_target, 5932), 2000) );

        // 18. Check for LOCK in DDRPHY_DP16_SYSCLK_PR_VALUE registers and DDRPHY_ADR_SYSCLK_PR_VALUE
        FAPI_INF("Checking for bang-bang lock %s ...", mss::c_str(i_target));
        FAPI_TRY( mss::check_bang_bang_lock(i_target) );

        // 19. Write 0b0 into the DDRPHY_PC_RESETS register bit 1. This write de-asserts the SYSCLK_RESET.
        FAPI_INF("deassert sysclk reset %s", mss::c_str(i_target));
        FAPI_TRY( mss::deassert_sysclk_reset(i_target), "deassert_sysclk_reset failed for %s", mss::c_str(i_target) );

        // 20. Write 8020h into the DDRPHY_ADR_SYSCLK_CNTL_PR Registers and
        // DDRPHY_DP16_SYSCLK_PR0/1 registers This write takes the dphy_nclk/
        // SysClk alignment circuit out of the Continuous Update mode.
        FAPI_INF("take sysclk alignment out of cont update mode %s", mss::c_str(i_target));
        FAPI_TRY( mss::setup_phase_rotator_control_registers(i_target, mss::OFF),
                  "set up of phase rotator controls failed (out of cont update) %s", mss::c_str(i_target) );

        // 21. Wait at least 32 dphy_nclk clock cycles.
        FAPI_DBG("Wait at least 32 memory clock cycles %s", mss::c_str(i_target));
        FAPI_TRY( fapi2::delay(mss::cycles_to_ns(i_target, 32), mss::cycles_to_simcycles(32)) );

        //
        // Done bang-bang-lock
        //

        //FIXME:    Need to code..      FAPI_TRY(mss_slew_cal(i_target),
        //      "mss_slew_cal Failed rc = 0x%08X", uint64_t(fapi2::current_err) );
        // slew cal successful
//    FAPI_TRY( mss::slew_cal(i_target), "slew_cal for %s failed", mss::c_str(i_target));

#ifdef LEAVES_OUTPUT_TO_DIMM_TRISTATE
        // Per J. Bialas, force_mclk_low can be dasserted.
        FAPI_TRY(mss::change_force_mclk_low(i_target, mss::LOW),
                 "force_mclk_low (set low) Failed rc = 0x%08X", uint64_t(fapi2::current_err) );
#endif

        // If mss_unmask_ddrphy_errors gets it's own bad rc,
        // it will commit the passed in rc (if non-zero), and return it's own bad rc.
        // Else if mss_unmask_ddrphy_errors runs clean,
        // it will just return the passed in rc.
        //FIXME:    Need to code..   FAPI_TRY(mss_unmask_ddrphy_errors(i_target, rc));

        FAPI_INF("********* %s complete *********", __func__);

    fapi_try_exit:
        return fapi2::current_err;

    }

}
OpenPOWER on IntegriCloud