@@ -1217,6 +1217,7 @@ exit:
}
static void occ_add_powercap_sensors(struct dt_node *power_mgt);
+static void occ_add_psr_sensors(struct dt_node *power_mgt);
static void occ_cmd_interface_init(void)
{
@@ -1262,6 +1263,9 @@ static void occ_cmd_interface_init(void)
/* Add powercap sensors to DT */
occ_add_powercap_sensors(power_mgt);
+
+ /* Add power-shifting-ratio CPU-GPU sensors to DT */
+ occ_add_psr_sensors(power_mgt);
}
/* Powercap interface */
@@ -1362,6 +1366,98 @@ int occ_set_powercap(int token, u32 pcap)
return opal_occ_command(&chips[i], token, &pcap_data);
};
+/* Power-Shifting Ratio */
+enum psr_type {
+ PSR_TYPE_CPU_TO_GPU, /* 0% Cap GPU first, 100% Cap CPU first */
+};
+
+static int opal_get_power_shifting_ratio(u32 handle, int token __unused,
+ int *ratio)
+{
+ struct occ_dynamic_data *ddata;
+ struct proc_chip *chip;
+ int type = (handle >> 24) & 0xF;
+ int i = handle & 0xF;
+
+ if (type != PSR_TYPE_CPU_TO_GPU)
+ return OPAL_UNSUPPORTED;
+
+ if (i > nr_occs || i < 0)
+ return OPAL_PARAMETER;
+
+ if (!(*chips[i].valid))
+ return OPAL_WRONG_STATE;
+
+ chip = get_chip(chips[i].chip_id);
+ ddata = get_occ_dynamic_data(chip);
+ *ratio = ddata->pwr_shifting_ratio;
+ return OPAL_SUCCESS;
+}
+
+static u8 psr_cdata;
+static struct opal_occ_cmd_data psr_data = {
+ .data = &psr_cdata,
+ .cmd = OCC_CMD_SET_POWER_SHIFTING_RATIO,
+};
+
+static int opal_set_power_shifting_ratio(u32 handle, int token, int ratio)
+{
+ struct occ_dynamic_data *ddata;
+ struct proc_chip *chip;
+ int type = (handle >> 24) & 0xF;
+ int i = handle & 0xF;
+
+ if (type != PSR_TYPE_CPU_TO_GPU)
+ return OPAL_UNSUPPORTED;
+
+ if (ratio < 0 || ratio > 100)
+ return OPAL_PARAMETER;
+
+ if (i > nr_occs || i < 0)
+ return OPAL_PARAMETER;
+
+ if (!(*chips[i].valid))
+ return OPAL_WRONG_STATE;
+
+ chip = get_chip(chips[i].chip_id);
+ ddata = get_occ_dynamic_data(chip);
+ if (ratio == ddata->pwr_shifting_ratio)
+ return OPAL_SUCCESS;
+
+ psr_cdata = ratio;
+ return opal_occ_command(&chips[i], token, &psr_data);
+}
+
+static void occ_add_psr_sensors(struct dt_node *power_mgt)
+{
+ struct dt_node *node, *cnode;
+ int i;
+
+ node = dt_new(power_mgt, "psr");
+ if (!node) {
+ prerror("OCC: Failed to create power-shifting-ratio node\n");
+ return;
+ }
+
+ for (i = 0; i < nr_occs; i++) {
+ char name[20];
+ u32 handle = (PSR_TYPE_CPU_TO_GPU << 24) | i;
+
+ cnode = dt_new_addr(node, "cpu-to-gpu", handle);
+ if (!cnode) {
+ prerror("OCC: Failed to create power-shifting-ratio node\n");
+ return;
+ }
+
+ snprintf(name, 20, "cpu_to_gpu_%d", chips[i].chip_id);
+ dt_add_property_string(cnode, "label", name);
+ dt_add_property_cells(cnode, "handle", handle);
+ }
+
+ opal_register(OPAL_GET_PSR, opal_get_power_shifting_ratio, 3);
+ opal_register(OPAL_SET_PSR, opal_set_power_shifting_ratio, 3);
+}
+
/* CPU-OCC PState init */
/* Called after OCC init on P8 and P9 */
void occ_pstates_init(void)
@@ -210,7 +210,9 @@
#define OPAL_IMC_COUNTERS_STOP 151
#define OPAL_GET_POWERCAP 152
#define OPAL_SET_POWERCAP 153
-#define OPAL_LAST 153
+#define OPAL_GET_PSR 154
+#define OPAL_SET_PSR 155
+#define OPAL_LAST 155
/* Device tree flags */
Add support to set the CPU-GPU power shifting ratio which is used by the OCC power capping algorithm. PSR value of 100 takes all power away from CPU first and a PSR value of 0 caps GPU first. Signed-off-by: Shilpasri G Bhat <shilpa.bhat@linux.vnet.ibm.com> --- hw/occ.c | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/opal-api.h | 4 ++- 2 files changed, 99 insertions(+), 1 deletion(-)