summaryrefslogtreecommitdiffstats
path: root/src/occ_405/wof/wof.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/occ_405/wof/wof.c')
-rw-r--r--src/occ_405/wof/wof.c202
1 files changed, 197 insertions, 5 deletions
diff --git a/src/occ_405/wof/wof.c b/src/occ_405/wof/wof.c
index b5df7b2..b54b691 100644
--- a/src/occ_405/wof/wof.c
+++ b/src/occ_405/wof/wof.c
@@ -45,7 +45,7 @@ extern GpeRequest G_wof_vfrt_req;
extern uint32_t G_pgpe_shared_sram_address;
extern uint32_t G_pgpe_pstate_table_address;
extern uint32_t G_pgpe_pstate_table_sz;
-
+extern uint32_t G_nest_frequency_mhz;
//******************************************************************************
// Globals
//******************************************************************************
@@ -933,6 +933,191 @@ void calculate_nest_leakage( void )
g_wof->idc_vdn = (G_oppb.iddq.ivdn*nest_mult) >> 10;
}
+
+/**
+ * calculate_effective_capacitance
+ *
+ * Description: Generic function to perform the effective capacitance
+ * calculations.
+ * C_eff = I / (V^1.3 * F)
+ *
+ * I is the AC component of Idd in 0.01 Amps (or10 mA)
+ * V is the silicon voltage in 100 uV
+ * F is the frequency in MHz
+ *
+ * Note: Caller must ensure they check for a 0 return value
+ * and disable wof if that is the case
+ *
+ * Param[in]: i_iAC - the AC component
+ * Param[in]: i_voltage - the voltage component in 100uV
+ * Param[in]: i_frequency - the frequency component
+ *
+ * Return: The calculated effective capacitance
+ */
+uint32_t calculate_effective_capacitance( uint32_t i_iAC,
+ uint32_t i_voltage,
+ uint32_t i_frequency )
+{
+
+ // Prevent divide by zero
+ if( i_frequency == 0 )
+ {
+ // Return 0 causing caller to disable wof.
+ return 0;
+ }
+
+ // Compute V^1.3 using a best-fit equation
+ // (V^1.3) = (21374 * (voltage in 100uV) - 50615296)>>10
+ uint32_t v_exp_1_dot_3 = (21374 * i_voltage - 50615296)>>10;
+
+ // Compute I / (V^1.3)
+ uint32_t I = i_iAC << 14; // * 16384
+
+ // Prevent divide by zero
+ if( v_exp_1_dot_3 == 0 )
+ {
+ // Return 0 causing caller to disable wof.
+ return 0;
+ }
+
+ uint32_t c_eff = (I / v_exp_1_dot_3);
+ c_eff = c_eff << 14; // * 16384
+
+ // Divide by frequency and return the final value.
+ // (I / (V^1.3 * F)) == I / V^1.3 /F
+ return c_eff / i_frequency;
+
+}
+
+
+
+/**
+ * calculate_ceff_ratio_vdn
+ *
+ * Description: Function to calculate the effective capacitance ratio
+ * for the nest
+ */
+void calculate_ceff_ratio_vdn( void )
+{
+ //TODO Read iac_tdp_vdn(@turbo) from OCCPstateParmBlock struct
+ g_wof->iac_tdp_vdn = 0;
+
+ // Calculate Ceff_tdp_vdn
+ // iac_tdp_vdn / (VOLTVDN^1.3 * Fnest)
+ g_wof->ceff_tdp_vdn =
+ calculate_effective_capacitance( g_wof->iac_tdp_vdn,
+ g_wof->voltvdn_sensor,
+ G_nest_frequency_mhz );
+
+ // Calculate ceff_vdn
+ // iac_vdn/ (VOLTVDN^1.3 * Fnest)
+ g_wof->ceff_vdn =
+ calculate_effective_capacitance( g_wof->iac_vdn,
+ g_wof->voltvdn_sensor,
+ G_nest_frequency_mhz );
+
+ // Prevent divide by zero
+ if( g_wof->ceff_tdp_vdn == 0 )
+ {
+ /*
+ * @errortype
+ * @moduleid CALC_CEFF_RATIO_VDN
+ * @reasoncode DIVIDE_BY_ZERO_ERROR
+ * @userdata1 0
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc Divide by zero error on ceff_vdn / ceff_tdp_vdn
+ */
+ errlHndl_t l_errl = createErrl(
+ CALC_CEFF_RATIO_VDN,
+ DIVIDE_BY_ZERO_ERROR,
+ OCC_NO_EXTENDED_RC,
+ ERRL_SEV_PREDICTIVE,
+ NULL,
+ DEFAULT_TRACE_SIZE,
+ 0,
+ 0 );
+
+ commitErrl( &l_errl );
+
+ // Return 0
+ g_wof->ceff_ratio_vdn = 0;
+
+ //TODO: RTC 166301 - call new disable_wof function
+ }
+ else
+ {
+ g_wof->ceff_ratio_vdn = g_wof->ceff_vdn / g_wof->ceff_tdp_vdn;
+ }
+}
+
+/**
+ * calculate_ceff_ratio_vdd
+ *
+ * Description: Function to calculate the effective capacitance ratio
+ * for the core
+ */
+void calculate_ceff_ratio_vdd( void )
+{
+ //TODO read iac_tdp_vdd from OCCPstateParmBlock struct
+ g_wof->iac_tdp_vdd = 0;
+
+ // Get Vturbo and convert to 100uV (mV -> 100uV) = mV*10
+ // Multiply by Vratio
+ uint32_t V = (G_oppb.operating_points[TURBO].vdd_mv*10) * g_wof->v_ratio;
+
+ // Get Fturbo and multiply by Fratio
+ uint32_t F = G_oppb.operating_points[TURBO].frequency_mhz * g_wof->f_ratio;
+
+ // Calculate ceff_tdp_vdd
+ // iac_tdp_vdd / ((Vturbo*Vratio)^1.3 * (Fturbo*Fratio))
+ g_wof->ceff_tdp_vdd =
+ calculate_effective_capacitance( g_wof->iac_tdp_vdd,
+ V,
+ F );
+
+ // Calculate ceff_vdd
+ // iac_vdd / (Vclip^1.3 * Fclip)
+ g_wof->ceff_vdd =
+ calculate_effective_capacitance( g_wof->iac_vdd,
+ g_wof->v_clip,
+ g_wof->f_clip );
+
+ // Prevent divide by zero
+ if( g_wof->ceff_tdp_vdd == 0 )
+ {
+ /*
+ * @errortype
+ * @moduleid CALC_CEFF_RATIO_VDD
+ * @reasoncode DIVIDE_BY_ZERO_ERROR
+ * @userdata1 0
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc Divide by zero error on ceff_vdd / ceff_tdp_vdd
+ */
+ errlHndl_t l_errl = createErrl(
+ CALC_CEFF_RATIO_VDD,
+ DIVIDE_BY_ZERO_ERROR,
+ OCC_NO_EXTENDED_RC,
+ ERRL_SEV_PREDICTIVE,
+ NULL,
+ DEFAULT_TRACE_SIZE,
+ 0,
+ 0 );
+
+ commitErrl( &l_errl );
+
+ // Return 0
+ g_wof->ceff_ratio_vdd = 0;
+
+ //TODO: RTC 166301 - call new disable_wof function
+ }
+ else
+ {
+ g_wof->ceff_ratio_vdd = g_wof->ceff_vdd / g_wof->ceff_tdp_vdd;
+ }
+}
+
+
+
/**
* calculate_AC_currents
*
@@ -1054,11 +1239,18 @@ int32_t calculate_multiplier( int32_t i_temp )
(int32_t)G_wof_iddq_mult_table[mult_idx+1][1]);
}
+/**
+ * read_sensor_data
+ *
+ * Description: One time place to read out all the sensors needed
+ * for wof calculations. First thing wof_main does.
+ */
void read_sensor_data( void )
{
// Read out necessary Sensor data for WOF calculation
- g_wof->curvdd_sensor = getSensorByGsid(CURVDD)->sample;
- g_wof->curvdn_sensor = getSensorByGsid(CURVDN)->sample;
- g_wof->voltvddsense_sensor = getSensorByGsid(VOLTVDDSENSE)->sample;
- g_wof->tempnest_sensor = getSensorByGsid(TEMPNEST)->sample;
+ g_wof->curvdd_sensor = getSensorByGsid(CURVDD)->sample;
+ g_wof->curvdn_sensor = getSensorByGsid(CURVDN)->sample;
+ g_wof->voltvddsense_sensor = getSensorByGsid(VOLTVDDSENSE)->sample;
+ g_wof->tempnest_sensor = getSensorByGsid(TEMPNEST)->sample;
+ g_wof->voltvdn_sensor = getSensorByGsid(VOLTVDN)->sample;
}
OpenPOWER on IntegriCloud