summaryrefslogtreecommitdiffstats
path: root/src/import/chips/p9/procedures/hwp/pm/p9_pm_pss_init.C
blob: 7840c2bfffdc95a008f6dfa6f6baa6f391312edf (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
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/pm/p9_pm_pss_init.C $      */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2018                        */
/* [+] 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_pm_pss_init.C
/// @brief Initializes P2S and HWC logic
///
// *HWP HW Owner        :   Greg Still <stillgs@us.ibm.com>
// *HWP Backup Owner    :   Prasad BG Ranganath <prasadbgr@in.ibm.com>
// *HWP FW Owner        :   Prem S Jha <premjha2@in.ibm.com>
// *HWP Team            :   PM
// *HWP Level           :   3
// *HWP Consumed by     :   HS

// -----------------------------------------------------------------------------
// Includes
// -----------------------------------------------------------------------------
#include <p9_pm_pss_init.H>
#include <p9_misc_scom_addresses.H>
#include <p9_misc_scom_addresses_fld.H>

// -----------------------------------------------------------------------------
// Function prototypes
// -----------------------------------------------------------------------------

//------------------------------------------------------------------------------
///
/// @brief Using configured attributed, performs the initialization of the PSS
///        function
///
/// @param[in] i_target Chip target
///
/// @return FAPI2_RC_SUCCESS on success, else error.
///
fapi2::ReturnCode pm_pss_init(
    const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target);

//------------------------------------------------------------------------------
///
/// @brief Performs the reset of the PSS function
///
/// @param[in] i_target Chip target
///
/// @return FAPI2_RC_SUCCESS on success, else error.
///
fapi2::ReturnCode pm_pss_reset(
    const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target);


// -----------------------------------------------------------------------------
// Function definitions
// -----------------------------------------------------------------------------

fapi2::ReturnCode p9_pm_pss_init(
    const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target,
    const p9pm::PM_FLOW_MODE i_mode)
{
    FAPI_IMP(">> p9_pm_pss_init");

    // Initialization:  perform order or dynamic operations to initialize
    // the PMC using necessary Platform or Feature attributes.
    if (i_mode == p9pm::PM_INIT)
    {
        FAPI_TRY(pm_pss_init(i_target), "Failed to initialize the PSS logic");
    }
    // Reset:  perform reset of PSS
    else if (i_mode == p9pm::PM_RESET)
    {
        FAPI_TRY(pm_pss_reset(i_target), "Failed to reset PSS logic.");
    }

fapi_try_exit:
    FAPI_IMP("<< p9_pm_pss_init");
    return fapi2::current_err;
}

fapi2::ReturnCode pm_pss_init(
    const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target)
{
    FAPI_IMP(">> pm_pss_init Enter");

    fapi2::buffer<uint64_t> l_data64;

    const uint8_t  l_default_apss_chip_select = 0;
    const uint8_t  l_default_spipss_frame_size = 0x20;
    const uint8_t  l_default_spipss_in_delay = 0;
    const uint8_t  l_default_spipss_clock_polarity = 0;
    const uint8_t  l_default_spipss_clock_phase = 0;
    const uint16_t l_default_attr_pm_spipss_clock_divider = 0xA;

    uint32_t l_attr_proc_pss_init_nest_frequency;
    uint8_t  l_attr_pm_apss_chip_select;
    uint8_t  l_attr_pm_spipss_frame_size;
    uint8_t  l_attr_pm_spipss_in_delay;
    uint8_t  l_attr_pm_spipss_clock_polarity;
    uint8_t  l_attr_pm_spipss_clock_phase;
    uint16_t l_attr_pm_spipss_clock_divider;
    uint32_t l_attr_pm_spipss_inter_frame_delay;

    uint32_t l_spipss_100ns_value;
    uint8_t  l_p2s_fsm_enable;
    uint8_t  l_p2s_nr_of_frames;
    uint8_t  l_hwctrl_fsm_enable;
    uint8_t  l_hwctrl_nr_of_frames;

    const fapi2::Target<fapi2::TARGET_TYPE_SYSTEM> l_sysTarget =
        i_target.getParent<fapi2::TARGET_TYPE_SYSTEM>();

    FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_FREQ_PB_MHZ, l_sysTarget,
                           l_attr_proc_pss_init_nest_frequency),
             "Error: Could not fetch the system Frequency")

    GETATTR_DEFAULT(fapi2::ATTR_PM_APSS_CHIP_SELECT,
                    "ATTR_PM_APSS_CHIP_SELECT",
                    i_target, l_attr_pm_apss_chip_select,
                    l_default_apss_chip_select);

    GETATTR_DEFAULT(fapi2::ATTR_PM_SPIPSS_FRAME_SIZE,
                    "ATTR_PM_SPIPSS_FRAME_SIZE",
                    i_target, l_attr_pm_spipss_frame_size,
                    l_default_spipss_frame_size);

    GETATTR_DEFAULT(fapi2::ATTR_PM_SPIPSS_IN_DELAY, "ATTR_PM_SPIPSS_IN_DELAY",
                    i_target, l_attr_pm_spipss_in_delay,
                    l_default_spipss_in_delay );

    GETATTR_DEFAULT(fapi2::ATTR_PM_SPIPSS_CLOCK_POLARITY,
                    "ATTR_PM_SPIPSS_CLOCK_POLARITY", i_target,
                    l_attr_pm_spipss_clock_polarity,
                    l_default_spipss_clock_polarity );

    GETATTR_DEFAULT(fapi2::ATTR_PM_SPIPSS_CLOCK_PHASE,
                    "ATTR_PM_SPIPSS_CLOCK_PHASE",
                    i_target, l_attr_pm_spipss_clock_phase,
                    l_default_spipss_clock_phase );

    GETATTR_DEFAULT(fapi2::ATTR_PM_SPIPSS_CLOCK_DIVIDER,
                    "ATTR_PM_SPIPSS_CLOCK_DIVIDER", i_target,
                    l_attr_pm_spipss_clock_divider,
                    l_default_attr_pm_spipss_clock_divider);

    FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_PM_SPIPSS_INTER_FRAME_DELAY_SETTING,
                           i_target, l_attr_pm_spipss_inter_frame_delay),
             "Error: Could not fetch inter frame delay");

    // ------------------------------------------
    //  -- Init procedure
    // ------------------------------------------

    //  ******************************************************************
    //     - set SPIPSS_ADC_CTRL_REG0 with the values read from attributes
    //  ******************************************************************
    FAPI_TRY(fapi2::getScom(i_target, PU_SPIMPSS_ADC_CTRL_REG0, l_data64));

    l_data64.insertFromRight<0, 6>(l_attr_pm_spipss_frame_size);
    l_data64.insertFromRight<12, 6>(l_attr_pm_spipss_in_delay);

    FAPI_TRY(fapi2::putScom(i_target, PU_SPIMPSS_ADC_CTRL_REG0, l_data64),
             "Error: failed to set the SPIPSS ADC CTRL REG 0 configuration");

    //  ******************************************************************
    //     - set SPIPSS_ADC_CTRL_REG1
    //         adc_fsm_enable = disable
    //         adc_device     = APSS
    //         adc_cpol       = 0
    //         adc_cpha       = 0
    //         adc_clock_divider = set to 10Mhz
    //         adc_nr_of_frames  = 0x16 (for auto 2 mode)
    //  ******************************************************************

    FAPI_TRY(fapi2::getScom(i_target, PU_SPIPSS_ADC_CTRL_REG1, l_data64));

    l_hwctrl_fsm_enable = 0x1;
    l_hwctrl_nr_of_frames = 0x10;

    l_data64.insertFromRight<0, 1>(l_hwctrl_fsm_enable);
    l_data64.insertFromRight<1, 1>(l_attr_pm_apss_chip_select);
    l_data64.insertFromRight<2, 1>(l_attr_pm_spipss_clock_polarity);
    l_data64.insertFromRight<3, 1>(l_attr_pm_spipss_clock_phase);
    l_data64.insertFromRight<4, 10>(l_attr_pm_spipss_clock_divider);
    l_data64.insertFromRight<14, 4>(l_hwctrl_nr_of_frames);

    FAPI_TRY(fapi2::putScom(i_target, PU_SPIPSS_ADC_CTRL_REG1, l_data64),
             "Error: failed to set the SPIPSS ADC CTRL REG 1 configuration");

    //  ******************************************************************
    //     - set SPIPSS_ADC_CTRL_REG2
    //  ******************************************************************

    FAPI_TRY(fapi2::getScom(i_target, PU_SPIPSS_ADC_CTRL_REG2, l_data64));
    l_data64.insertFromRight<0, 17>(l_attr_pm_spipss_inter_frame_delay);
    FAPI_TRY(fapi2::putScom(i_target, PU_SPIPSS_ADC_CTRL_REG2, l_data64),
             "Error: failed to set the SPIPSS ADC CTRL REG 2 configuration");

    //  ******************************************************************
    //     - clear SPIPSS_ADC_Wdata_REG
    //  ******************************************************************
    l_data64.flush<0>();
    FAPI_TRY(fapi2::putScom(i_target, PU_SPIPSS_ADC_WDATA_REG, l_data64),
             "Error: Failed to clear SPIPSS ADC WDATA");

    //  ******************************************************************
    //     - set SPIPSS_P2S_CTRL_REG0
    //  ******************************************************************

    FAPI_TRY(fapi2::getScom(i_target, PU_SPIPSS_P2S_CTRL_REG0, l_data64));

    l_data64.insertFromRight<0, 6>(l_attr_pm_spipss_frame_size);
    l_data64.insertFromRight<12, 6>(l_attr_pm_spipss_in_delay);

    FAPI_TRY(fapi2::putScom(i_target, PU_SPIPSS_P2S_CTRL_REG0, l_data64),
             "Error: Failed to set SPIPSS P2S CTRL REG 0");

    //  ******************************************************************
    //     - set SPIPSS_P2S_CTRL_REG1
    //         p2s_fsm_enable = disable
    //         p2s_device     = APSS
    //         p2s_cpol       = 0
    //         p2s_cpha       = 0
    //         p2s_clock_divider = set to 10Mhz
    //         p2s_nr_of_frames = 1 (for auto 2 mode)
    //  ******************************************************************

    FAPI_TRY(fapi2::getScom(i_target, PU_SPIPSS_P2S_CTRL_REG1, l_data64));

    l_p2s_fsm_enable = 0x1;
    l_p2s_nr_of_frames = 0x1;

    l_data64.insertFromRight<0, 1>(l_p2s_fsm_enable);
    l_data64.insertFromRight<1, 1>(l_attr_pm_apss_chip_select);
    l_data64.insertFromRight<2, 1>(l_attr_pm_spipss_clock_polarity);
    l_data64.insertFromRight<3, 1>(l_attr_pm_spipss_clock_phase);
    l_data64.insertFromRight<4, 10>(l_attr_pm_spipss_clock_divider);
    l_data64.insertFromRight<17, 1>(l_p2s_nr_of_frames);

    FAPI_TRY(fapi2::putScom(i_target, PU_SPIPSS_P2S_CTRL_REG1, l_data64),
             "Error: Failed to set SPIPSS P2S CTRL REG 1");

    //  ******************************************************************
    //     - set SPIPSS_P2S_CTRL_REG2
    //  ******************************************************************

    FAPI_TRY(fapi2::getScom(i_target, PU_SPIPSS_P2S_CTRL_REG2, l_data64));
    l_data64.insertFromRight<0, 17>(l_attr_pm_spipss_inter_frame_delay);
    FAPI_TRY(fapi2::putScom(i_target, PU_SPIPSS_P2S_CTRL_REG2, l_data64),
             "Error: Failed to set SPIPSS P2S CTRL REG 2");

    //  ******************************************************************
    //     - clear SPIPSS_P2S_Wdata_REG
    //  ******************************************************************
    l_data64.flush<0>();
    FAPI_TRY(fapi2::putScom(i_target, PU_SPIPSS_P2S_WDATA_REG, l_data64),
             "Error: Failed to clear SPI PSS P2S WDATA");

    //  ******************************************************************
    //     - Set 100ns Register for Interframe delay
    //  ******************************************************************
    l_spipss_100ns_value = l_attr_proc_pss_init_nest_frequency / 40;
    FAPI_TRY(fapi2::getScom(i_target, PU_SPIPSS_100NS_REG, l_data64));
    l_data64.insertFromRight<0, 32>(l_spipss_100ns_value);
    FAPI_TRY(fapi2::putScom(i_target, PU_SPIPSS_100NS_REG, l_data64),
             "Error: Failed to set 100ns clear SPI PSS P2S WDATA");

fapi_try_exit:
    FAPI_IMP("<< pm_pss_init");
    return fapi2::current_err;
}


fapi2::ReturnCode pm_pss_reset(
    const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target)
{
    FAPI_IMP(">> pm_pss_reset");

    fapi2::buffer<uint64_t> l_data64;
    uint32_t l_pollcount = 0;
    uint32_t l_max_polls;
    // timeout period is 10 millisecond. (Far longer than needed)
    const uint32_t l_pss_timeout_us = 10000;
    const uint32_t l_pss_poll_interval_us = 10;

    //  ******************************************************************
    //     - Poll status register for ongoing or no errors to give the
    //       chance for on-going operations to complete
    //  ******************************************************************

    FAPI_INF("Polling for ADC on-going to go low ... ");
    l_max_polls = l_pss_timeout_us / l_pss_poll_interval_us;

    for (l_pollcount = 0; l_pollcount < l_max_polls; l_pollcount++)
    {
        FAPI_TRY(fapi2::getScom(i_target, PU_SPIPSS_ADC_STATUS_REG, l_data64));

        // ADC on-going complete
        if (l_data64.getBit<PU_SPIPSS_ADC_STATUS_REG_HWCTRL_ONGOING>() == 0)
        {
            FAPI_INF("All frames sent from ADC to the APSS device.");
            break;
        }

        // ADC error
        FAPI_ASSERT(!l_data64.getBit<PU_SPIPSS_ADC_STATUS_REG_HWCTRL_FSM_ERR>(),
                    fapi2::PM_PSS_ADC_ERROR()
                    .set_CHIP(i_target)
                    .set_POLLCOUNT(l_pollcount),
                    "Error while sending the frames from ADC to APSS device");

        FAPI_DBG("Delay before next poll");
        fapi2::delay(l_pss_poll_interval_us * 1000, 1000);
    }

    // Write attempted while Bridge busy
    if(l_data64.getBit<PU_SPIPSS_ADC_STATUS_REG_HWCTRL_WRITE_WHILE_FSM_BUSY_ERR>() == 1)
    {
        FAPI_INF("SPIP2S Write While Bridge Busy bit asserted. May cause "
                 "undefined bridge behavior. Will be cleared during reset");
    }

    // Polling timeout
    if (l_pollcount >= l_max_polls)
    {
        FAPI_INF("WARNING: SPI ADC did not go to idle in at least %d us. "
                 "Reset of PSS macro is commencing anyway", l_pss_timeout_us);
    }

    //  ******************************************************************
    //     - Poll status register for ongoing or errors to give the
    //       chance for on-going operations to complete
    //  ******************************************************************

    FAPI_INF("Polling for P2S on-going to go low ... ");

    for (l_pollcount = 0; l_pollcount < l_max_polls; l_pollcount++)
    {
        FAPI_TRY(fapi2::getScom(i_target, PU_SPIPSS_P2S_STATUS_REG, l_data64));

        //P2S On-going complete
        if (l_data64.getBit<0>() == 0)
        {
            FAPI_INF("All frames sent from P2S to the APSS device.");
            break;
        }

        // P2S error
        FAPI_ASSERT(!l_data64.getBit<PU_SPIPSS_P2S_STATUS_REG_FSM_ERR>(),
                    fapi2::PM_PSS_P2S_ERROR()
                    .set_CHIP(i_target)
                    .set_POLLCOUNT(l_pollcount),
                    "Error while sending the frames from P2S to APSS device");

        FAPI_DBG("Delay before next poll");
        fapi2::delay(l_pss_poll_interval_us * 1000, 1000);
    }

    FAPI_ASSERT_NOEXIT(!l_data64.getBit<PU_SPIPSS_P2S_STATUS_REG_WRITE_WHILE_BRIDGE_BUSY_ERR>(),
                       fapi2::PM_PSS_ADC_WRITE_WHILE_BUSY()
                       .set_CHIP(i_target)
                       .set_POLLCOUNT(l_pollcount),
                       "SPIP2S Write While Bridge Busy bit asserted. Will be cleared with coming reset");

    FAPI_ASSERT_NOEXIT(l_pollcount < l_max_polls,
                       fapi2::PM_PSS_ADC_TIMEOUT()
                       .set_CHIP(i_target)
                       .set_POLLCOUNT(l_pollcount)
                       .set_MAXPOLLS(l_max_polls)
                       .set_TIMEOUTUS(l_pss_timeout_us),
                       "SPI P2S did not go to idle in at least % d us. "
                       "Reset of PSS macro is commencing anyway", l_pss_timeout_us );

    //  ******************************************************************
    //     - Resetting both ADC and P2S bridge
    //  ******************************************************************

    FAPI_INF("Resetting P2S and ADC bridges.");

    l_data64.flush<0>();
    // Need to write 01
    l_data64.setBit < PU_SPIPSS_ADC_RESET_REGISTER_HWCTRL + 1 > ();

    FAPI_TRY(fapi2::putScom(i_target, PU_SPIPSS_ADC_RESET_REGISTER, l_data64),
             "Error: Could not reset ADC bridge");
    FAPI_TRY(fapi2::putScom(i_target, PU_SPIPSS_P2S_RESET_REGISTER, l_data64),
             "Error: Could not reset P2S bridge");

    // Clearing reset for cleanliness
    l_data64.flush<0>();
    FAPI_TRY(fapi2::putScom(i_target, PU_SPIPSS_ADC_RESET_REGISTER, l_data64),
             "Error: Could not clear the ADC reset register");
    FAPI_TRY(fapi2::putScom(i_target, PU_SPIPSS_P2S_RESET_REGISTER, l_data64),
             "Error: Could not clear the P2S reset register");

fapi_try_exit:
    FAPI_IMP(" << pm_pss_reset");
    return fapi2::current_err;
}
OpenPOWER on IntegriCloud