aboutsummaryrefslogtreecommitdiff
path: root/hw/occ.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/occ.c')
-rw-r--r--hw/occ.c63
1 files changed, 52 insertions, 11 deletions
diff --git a/hw/occ.c b/hw/occ.c
index 0e3d953..987d007 100644
--- a/hw/occ.c
+++ b/hw/occ.c
@@ -49,18 +49,24 @@ struct occ_pstate_entry {
u32 freq_khz;
};
+/*
+ * OCC-OPAL Shared Memory Region Version 2
+ * https://github.com/open-power/occ/blob/master/src/occ/proc/proc_pstate.h
+ * Interface defined in 'sapphire_table_t'
+ */
struct occ_pstate_table {
u8 valid;
u8 version;
u8 throttle;
s8 pstate_min;
s8 pstate_nom;
- s8 pstate_max;
- u8 spare1;
- u8 spare2;
+ s8 pstate_turbo;
+ s8 pstate_ultra_turbo;
+ u8 spare;
u64 reserved;
struct occ_pstate_entry pstates[MAX_PSTATES];
-};
+ s8 core_max[16];
+} __packed;
DEFINE_LOG_ENTRY(OPAL_RC_OCC_LOAD, OPAL_PLATFORM_ERR_EVT, OPAL_OCC,
OPAL_CEC_HARDWARE, OPAL_PREDICTIVE_ERR_GENERAL,
@@ -142,11 +148,13 @@ static bool add_cpu_pstate_properties(s8 *pstate_nom)
uint64_t occ_data_area;
struct occ_pstate_table *occ_data;
struct dt_node *power_mgt;
- u8 nr_pstates;
+ u8 nr_pstates, nr_cores = 0;
+ s8 pmax;
/* Arrays for device tree */
u32 *dt_id, *dt_freq;
u8 *dt_vdd, *dt_vcs;
- bool rc;
+ s8 *dt_core_max = NULL;
+ bool rc, ultra_turbo_en;
int i;
prlog(PR_DEBUG, "OCC: CPU pstate state device tree init\n");
@@ -171,10 +179,18 @@ static bool add_cpu_pstate_properties(s8 *pstate_nom)
return false;
}
- nr_pstates = occ_data->pstate_max - occ_data->pstate_min + 1;
+ if (occ_data->version > 1 &&
+ occ_data->pstate_ultra_turbo > occ_data->pstate_turbo)
+ ultra_turbo_en = true;
+ else
+ ultra_turbo_en = false;
+
+ pmax = ultra_turbo_en ? occ_data->pstate_ultra_turbo :
+ occ_data->pstate_turbo;
+ nr_pstates = pmax - occ_data->pstate_min + 1;
prlog(PR_DEBUG, "OCC: Min %d Nom %d Max %d Nr States %d\n",
occ_data->pstate_min, occ_data->pstate_nom,
- occ_data->pstate_max, nr_pstates);
+ pmax, nr_pstates);
if (nr_pstates <= 1 || nr_pstates > 128) {
prerror("OCC: OCC range is not valid\n");
@@ -215,6 +231,18 @@ static bool add_cpu_pstate_properties(s8 *pstate_nom)
goto out_free_vdd;
}
+ if (ultra_turbo_en) {
+ nr_cores = get_available_nr_cores_in_chip(chip->id);
+ dt_core_max = malloc(nr_cores * sizeof(s8));
+ if (!dt_core_max) {
+ prerror("OCC: dt_core_max alloc failure\n");
+ goto out_free_vcs;
+ }
+
+ for (i = 0; i < nr_cores; i++)
+ dt_core_max[i] = occ_data->core_max[i];
+ }
+
for( i=0; i < nr_pstates; i++) {
dt_id[i] = occ_data->pstates[i].id;
dt_freq[i] = occ_data->pstates[i].freq_khz/1000;
@@ -223,18 +251,31 @@ static bool add_cpu_pstate_properties(s8 *pstate_nom)
}
/* Add the device-tree entries */
- dt_add_property(power_mgt, "ibm,pstate-ids", dt_id, nr_pstates * 4);
- dt_add_property(power_mgt, "ibm,pstate-frequencies-mhz", dt_freq, nr_pstates * 4);
+ dt_add_property(power_mgt, "ibm,pstate-ids", dt_id,
+ nr_pstates * sizeof(u32));
+ dt_add_property(power_mgt, "ibm,pstate-frequencies-mhz", dt_freq,
+ nr_pstates * sizeof(u32));
dt_add_property(power_mgt, "ibm,pstate-vdds", dt_vdd, nr_pstates);
dt_add_property(power_mgt, "ibm,pstate-vcss", dt_vcs, nr_pstates);
dt_add_property_cells(power_mgt, "ibm,pstate-min", occ_data->pstate_min);
dt_add_property_cells(power_mgt, "ibm,pstate-nominal", occ_data->pstate_nom);
- dt_add_property_cells(power_mgt, "ibm,pstate-max", occ_data->pstate_max);
+ dt_add_property_cells(power_mgt, "ibm,pstate-max", pmax);
+
+ if (ultra_turbo_en) {
+ dt_add_property_cells(power_mgt, "ibm,pstate-turbo",
+ occ_data->pstate_turbo);
+ dt_add_property_cells(power_mgt, "ibm,pstate-ultra-turbo",
+ occ_data->pstate_ultra_turbo);
+ dt_add_property(power_mgt, "ibm,pstate-core-max", dt_core_max,
+ nr_cores);
+ free(dt_core_max);
+ }
/* Return pstate to set for each core */
*pstate_nom = occ_data->pstate_nom;
rc = true;
+out_free_vcs:
free(dt_vcs);
out_free_vdd:
free(dt_vdd);