Skip to content

Commit faac790

Browse files
stillgsdcrowell77
authored andcommitted
p9_pm_pfet_init: redo log2 function to fix delay settings
- fixed the erroneous use of refclk vs pb_frequency/4 for the PPM counter - fixed inherent counter 2x delay insertion - rebase Change-Id: Ie91869e23d0420c5e8dd113d5e4f2686e2f9fa64 RTC: 167071 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/34687 Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com> Tested-by: Hostboot CI <hostboot-ci+hostboot@us.ibm.com> Reviewed-by: Prem Shanker Jha <premjha2@in.ibm.com> Reviewed-by: Brian T. Vanderpool <vanderp@us.ibm.com> Reviewed-by: AMIT KUMAR <akumar3@us.ibm.com> Reviewed-by: Jennifer A. Stofer <stofer@us.ibm.com> Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/34688 Reviewed-by: Hostboot Team <hostboot@us.ibm.com> Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com> Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com> Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
1 parent d9e7745 commit faac790

File tree

1 file changed

+91
-90
lines changed

1 file changed

+91
-90
lines changed

src/import/chips/p9/procedures/hwp/pm/p9_pm_pfet_init.C

Lines changed: 91 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
/* */
66
/* OpenPOWER HostBoot Project */
77
/* */
8-
/* Contributors Listed Below - COPYRIGHT 2015,2016 */
8+
/* Contributors Listed Below - COPYRIGHT 2015,2017 */
99
/* [+] International Business Machines Corp. */
1010
/* */
1111
/* */
@@ -138,8 +138,8 @@ fapi2::ReturnCode pfet_set_voff(
138138
/// @return delays in this register are in terms of PPM clock period
139139

140140
uint8_t convert_delay_to_value (
141-
const uint32_t i_delay,
142-
const uint32_t i_attr_proc_nest_frequency);
141+
const uint32_t i_delay_ns,
142+
const uint32_t i_proc_nest_frequency_MHz);
143143

144144
// ----------------------------------------------------------------------
145145
// Function definitions
@@ -222,7 +222,7 @@ fapi2::ReturnCode pfet_init(
222222
uint8_t l_pfet_powerup_delay_value = 0;
223223
uint8_t l_pfet_powerdown_delay_value = 0;
224224

225-
uint32_t l_proc_refclk_frequency;
225+
uint32_t l_proc_nest_frequency;
226226
uint32_t l_pfet_powerup_delay_ns;
227227
uint32_t l_pfet_powerdown_delay_ns;
228228
uint8_t l_pfet_vdd_voff_sel;
@@ -255,11 +255,11 @@ fapi2::ReturnCode pfet_init(
255255
// ******************************************************************
256256
const fapi2::Target<fapi2::TARGET_TYPE_SYSTEM> FAPI_SYSTEM;
257257
/// ----------------------------------------------------------
258-
l_proc_refclk_frequency = 0;
259-
FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_FREQ_PROC_REFCLOCK_KHZ,
258+
l_proc_nest_frequency = 0;
259+
FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_FREQ_PB_MHZ,
260260
FAPI_SYSTEM,
261-
l_proc_refclk_frequency),
262-
"Error getting ATTR_FREQ_PROC_REFCLOCK");
261+
l_proc_nest_frequency),
262+
"Error getting ATTR_FREQ_PB_MHZ");
263263

264264

265265
/// ----------------------------------------------------------
@@ -293,24 +293,24 @@ fapi2::ReturnCode pfet_init(
293293

294294
l_pfet_powerup_delay_value =
295295
convert_delay_to_value( l_pfet_powerup_delay_ns,
296-
l_proc_refclk_frequency);
296+
l_proc_nest_frequency);
297297

298298
l_pfet_powerdown_delay_value =
299299
convert_delay_to_value( l_pfet_powerdown_delay_ns,
300-
l_proc_refclk_frequency);
300+
l_proc_nest_frequency);
301301

302302

303303
FAPI_DBG("PFET Power Up Delay");
304304
FAPI_DBG(" ATTR_PM_PFET_POWERUP_DELAY_NS : %d (0x%X)",
305-
l_pfet_powerup_delay_value,
306-
l_pfet_powerup_delay_value);
307-
FAPI_DBG(" pfet_powerup_delay_value : %X", l_pfet_powerup_delay_value);
305+
l_pfet_powerup_delay_ns,
306+
l_pfet_powerup_delay_ns);
307+
FAPI_DBG(" pfet_powerup_delay_value : %X", l_pfet_powerup_delay_value);
308308

309309
FAPI_DBG("PFET Power Down Delay");
310310
FAPI_DBG(" ATTR_PM_PFET_POWERDOWN_DELAY_NS : %d (0x%X)",
311-
l_pfet_powerdown_delay_value,
312-
l_pfet_powerdown_delay_value);
313-
FAPI_DBG(" pfet_powerdown_delay_value : %X", l_pfet_powerdown_delay_value);
311+
l_pfet_powerdown_delay_ns,
312+
l_pfet_powerdown_delay_ns);
313+
FAPI_DBG(" pfet_powerdown_delay_value : %X", l_pfet_powerdown_delay_value);
314314

315315

316316
// ******************************************************************
@@ -455,90 +455,91 @@ fapi_try_exit:
455455
//------------------------------------------------------------------------------
456456
// convert_delay_to_value
457457
// Helper function to convert time values (binary in ns)to hardware delays
458+
//
459+
// The hardware uses a 1 in the power of 2 bit position of a 16 bit counter
460+
// to indicate a delay match. As the LSb of the counter will become a 1 every
461+
// other cycle, there is an inherent multiply by 2 built in. Thus, the smallest
462+
// delay possible is 2 x the counter frequency (eg for a 2GHz nest with PFET
463+
// controller logic running at /4 of that indicates a 2ns cycle time. With a
464+
// power of 2 of 0 (eg bit 15 of the counter) indicates a match on that LSb
465+
// every 4ns).
458466
//------------------------------------------------------------------------------
459467
// @todo can this be done in a better way?
460468
uint8_t
461-
convert_delay_to_value (uint32_t i_delay,
462-
uint32_t i_proc_nest_frequency)
469+
convert_delay_to_value (const uint32_t i_delay_ns,
470+
const uint32_t i_proc_nest_frequency_MHz)
463471
{
464-
uint8_t pfet_delay_value;
472+
uint8_t pfet_delay_value = 0xFF; // An illegal value
465473
uint64_t dly;
466-
// attr_proc_nest_frequency [MHz]
467-
// delay [ns]
468-
// pfet_delay_value = 15 - log2( i_delay * i_attr_proc_nest_frequency/1000);
469-
// since log2 function is not available, this is done manually
474+
475+
// i_attr_proc_nest_frequency_MHz (Mcycles/s * M/M = cycles/us)
476+
477+
// PPM cycle time (ns/cycle) = 1/PPM frequency_MHz [1/(cycles/us)]
478+
// = 1/PPM frequency_MHz [us/cycle]
479+
// = (1/PPM frequency_MHz)* 1000 ns/cycle
480+
//
481+
// PPM frequency_MHz (cycles/us) = i_attr_proc_nest_frequency_MHz / 4 (cycles/us)
482+
//
483+
// delay_ns = 2 * PPM cycle time (ns) * 2**(15-N)
484+
// where N (pfet_delay value) is the bit position of a 16 bit counter
485+
// that has the least significant bit toggling every other cycle.
486+
// The every other cycle is the reason for the 2 * cycle time.
487+
//
488+
// delay_ns / (2 * PPM cycle time (ns)) = 2**(15-N)
489+
// (delay_ns / 2) * PPM frequency (cycles/ns) = 2**(15-N)
490+
// (delay_ns / 2) * PPM frequency_MHz/1000 (cycles/us * us/1000ns -> cycles/ns) = 2**(15-N)
491+
// log2(delay_ns/2 * PPM Frequency_MHz/1000) = 15-N
492+
// N (pfet_delay_value) = 15 - log2(delay_ns/2 * PPM Frequency_MHz/1000);
493+
// N (pfet_delay_value) = 15 - log2(i_delay_ns/2 * (i_attr_proc_nest_frequency_MHz/4)/1000);
494+
//
495+
// dly = i_delay_ns/2 * (i_attr_proc_nest_frequency_MHz/4)/1000
470496
// pfet_delay_value = 15 - log2( dly );
471-
dly = ( i_delay * i_proc_nest_frequency );
472497

473-
if ( dly <= 1400 )
474-
{
475-
pfet_delay_value = 15 - 0 ;
476-
}
477-
else if (( 1400 < dly ) && ( dly <= 2800 ) )
478-
{
479-
pfet_delay_value = 15 - 1 ;
480-
}
481-
else if (( 2800 < dly ) && ( dly <= 5600 ) )
482-
{
483-
pfet_delay_value = 15 - 2 ;
484-
}
485-
else if (( 5600 < dly ) && ( dly <= 11500 ) )
486-
{
487-
pfet_delay_value = 15 - 3 ;
488-
}
489-
else if (( 11500 < dly ) && ( dly <= 23000 ) )
490-
{
491-
pfet_delay_value = 15 - 4 ;
492-
}
493-
else if (( 23000 < dly ) && ( dly <= 46000 ) )
494-
{
495-
pfet_delay_value = 15 - 5 ;
496-
}
497-
else if (( 46000 < dly ) && ( dly <= 92000 ) )
498-
{
499-
pfet_delay_value = 15 - 6 ;
500-
}
501-
else if (( 92000 < dly ) && ( dly <= 182000 ) )
502-
{
503-
pfet_delay_value = 15 - 7 ;
504-
}
505-
else if (( 182000 < dly ) && ( dly <= 364000 ) )
506-
{
507-
pfet_delay_value = 15 - 8 ;
508-
}
509-
else if (( 364000 < dly ) && ( dly <= 728000 ) )
510-
{
511-
pfet_delay_value = 15 - 9 ;
512-
}
513-
else if (( 728000 < dly ) && ( dly <= 1456000 ) )
514-
{
515-
pfet_delay_value = 15 - 10;
516-
}
517-
else if (( 1456000 < dly ) && ( dly <= 2912000 ) )
518-
{
519-
pfet_delay_value = 15 - 11;
520-
}
521-
else if (( 2912000 < dly ) && ( dly <= 5824000 ) )
522-
{
523-
pfet_delay_value = 15 - 12;
524-
}
525-
else if (( 5824000 < dly ) && ( dly <= 11648000 ))
526-
{
527-
pfet_delay_value = 15 - 13;
528-
}
529-
else if (( 11648000 < dly ) && ( dly <= 23296000 ))
530-
{
531-
pfet_delay_value = 15 - 14;
532-
}
533-
else if ( 23296000 < dly )
534-
{
535-
pfet_delay_value = 15 - 15;
536-
}
537-
else
498+
dly = i_delay_ns / 2 * (i_proc_nest_frequency_MHz / 4 ) / 1000;
499+
FAPI_DBG("i_delay_ns = %d (0x%X), i_proc_nest_frequency_MHz = %d (0x%X), "
500+
"ppm_frequency_MHz = %d (0x%X), dly = %d (0x%08llX)",
501+
i_delay_ns, i_delay_ns,
502+
i_proc_nest_frequency_MHz, i_proc_nest_frequency_MHz,
503+
i_proc_nest_frequency_MHz / 4, i_proc_nest_frequency_MHz / 4,
504+
dly, dly );
505+
506+
uint16_t pow2bit_value = 0x8000;
507+
uint16_t value = (uint16_t)dly;
508+
509+
// For log2, walk a 1 across the data to find the 2**i that is less than
510+
// or equal.
511+
for (uint32_t i = 0; i < 16; ++i)
538512
{
539-
pfet_delay_value = 15 - 15;
513+
if (pow2bit_value == value) // Matched exactly. We found the bit
514+
{
515+
FAPI_DBG("EQ i = %d pow2bit_value = 0x%04X, value = 0x%04X", i, pow2bit_value, value);
516+
pfet_delay_value = i;
517+
break;
518+
}
519+
else if (pow2bit_value < value) // Found bit that was less than
520+
{
521+
if (i == 0)
522+
{
523+
FAPI_DBG("LT but saturated: i = %d pow2bit_value = 0x%04X, value = 0x%04X", i, pow2bit_value, value);
524+
pfet_delay_value = i;
525+
}
526+
else
527+
{
528+
FAPI_DBG("LT but rounding up: i = %d pow2bit_value = 0x%04X, value = 0x%04X", i, pow2bit_value, value);
529+
pfet_delay_value = i - 1; // Power of 2 eg round up
530+
}
531+
532+
break;
533+
}
534+
else // shift it right to check the next bit
535+
{
536+
pow2bit_value >>= 1;
537+
}
540538
}
541539

540+
FAPI_DBG("pfet_delay_value = %d (0x%X))",
541+
pfet_delay_value, pfet_delay_value );
542+
542543
return (pfet_delay_value);
543544
}
544545

0 commit comments

Comments
 (0)