aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/Makefile.inc2
-rw-r--r--core/psr.c42
-rw-r--r--doc/device-tree/ibm,opal/power-mgt/psr.rst53
-rw-r--r--doc/opal-api/opal-power-shift-ratio.rst79
-rw-r--r--hw/occ.c95
-rw-r--r--include/opal-api.h4
-rw-r--r--include/psr.h46
7 files changed, 319 insertions, 2 deletions
diff --git a/core/Makefile.inc b/core/Makefile.inc
index b3c9e91..f2de2f6 100644
--- a/core/Makefile.inc
+++ b/core/Makefile.inc
@@ -8,7 +8,7 @@ CORE_OBJS += pci-opal.o fast-reboot.o device.o exceptions.o trace.o affinity.o
CORE_OBJS += vpd.o hostservices.o platform.o nvram.o nvram-format.o hmi.o
CORE_OBJS += console-log.o ipmi.o time-utils.o pel.o pool.o errorlog.o
CORE_OBJS += timer.o i2c.o rtc.o flash.o sensor.o ipmi-opal.o
-CORE_OBJS += flash-subpartition.o bitmap.o buddy.o pci-quirk.o powercap.o
+CORE_OBJS += flash-subpartition.o bitmap.o buddy.o pci-quirk.o powercap.o psr.o
ifeq ($(SKIBOOT_GCOV),1)
CORE_OBJS += gcov-profiling.o
diff --git a/core/psr.c b/core/psr.c
new file mode 100644
index 0000000..d3ff6ac
--- /dev/null
+++ b/core/psr.c
@@ -0,0 +1,42 @@
+/* Copyright 2017 IBM 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.
+ */
+
+#include <psr.h>
+
+static int opal_get_power_shift_ratio(u32 handle, int token __unused,
+ u32 *ratio)
+{
+ if (!ratio || !opal_addr_valid(ratio))
+ return OPAL_PARAMETER;
+
+ if (psr_get_class(handle) == PSR_CLASS_OCC)
+ return occ_get_psr(handle, ratio);
+
+ return OPAL_UNSUPPORTED;
+};
+
+opal_call(OPAL_GET_POWER_SHIFT_RATIO, opal_get_power_shift_ratio, 3);
+
+static int opal_set_power_shift_ratio(u32 handle, int token,
+ u32 ratio)
+{
+ if (psr_get_class(handle) == PSR_CLASS_OCC)
+ return occ_set_psr(handle, token, ratio);
+
+ return OPAL_UNSUPPORTED;
+};
+
+opal_call(OPAL_SET_POWER_SHIFT_RATIO, opal_set_power_shift_ratio, 3);
diff --git a/doc/device-tree/ibm,opal/power-mgt/psr.rst b/doc/device-tree/ibm,opal/power-mgt/psr.rst
new file mode 100644
index 0000000..edae8da
--- /dev/null
+++ b/doc/device-tree/ibm,opal/power-mgt/psr.rst
@@ -0,0 +1,53 @@
+power-mgt/psr
+------------------
+
+Some systems allow modification of how power consumption throttling
+is balanced between entities in a system. A typical one may be how the power
+management complex should balance throttling CPU versus the GPU. An OPAL
+call can be used to set these ratios, which are described in the device
+tree.
+
+In the future, there may be more available settings than just CPU
+versus GPU.
+
+Each child node in the "psr" node represents a configurable psr
+sensor.
+
+For example : ::
+ cpu-to-gpu@1
+
+The compatible property is set to "ibm,opal-power-shift-ratio".
+
+Each child node has below properties:
+
+`handle`
+ Handle to indicate the type of psr
+
+`label`
+ Name of the psr sensor
+
+The format of the handle is internal, and ``not`` ABI, although
+currently it uses the following encoding ::
+
+ | Class |Reserved| RID | Type |
+ |-------|--------|------|------|
+
+.. code-block:: dts
+
+ power-mgt {
+ psr {
+ compatible = "ibm,opal-power-shift-ratio"
+
+ cpu-to-gpu@0 {
+ name = "cpu-to-gpu"
+ handle = <0x00000000>
+ label = "cpu_to_gpu_0"
+ };
+
+ cpu-to-gpu@1 {
+ name = "cpu-to-gpu"
+ handle = <0x00000100>
+ label = "cpu_to_gpu_1"
+ };
+ };
+ };
diff --git a/doc/opal-api/opal-power-shift-ratio.rst b/doc/opal-api/opal-power-shift-ratio.rst
new file mode 100644
index 0000000..7f1f71f
--- /dev/null
+++ b/doc/opal-api/opal-power-shift-ratio.rst
@@ -0,0 +1,79 @@
+.. _opal-psr:
+
+OPAL_GET_POWER_SHIFT_RATIO
+==============================
+OPAL call to read the power-shifting-ratio using a handle to identify
+the type (e.g CPU vs. GPU, CPU vs. MEM) which is exported via
+device-tree.
+
+The call can be asynchronus, where the token parameter is used to wait
+for the completion.
+
+Parameters
+----------
+::
+ u32 handle
+ int token
+ u32 *ratio
+
+Returns
+-------
+OPAL_SUCCESS
+ Success
+
+OPAL_PARAMETER
+ Invalid ratio pointer
+
+OPAL_UNSUPPORTED
+ No support for reading psr
+
+OPAL_HARDWARE
+ Unable to procced due to the current hardware state
+
+OPAL_ASYNC_COMPLETION
+ Request was sent and an async completion message will be sent with
+ token and status of the request.
+
+OPAL_SET_POWER_SHIFT_RATIO
+==============================
+OPAL call to set power-shifting-ratio using a handle to identify
+the type of PSR which is exported in device-tree. This call can be
+asynchronus where the token parameter is used to wait for the
+completion.
+
+Parameters
+----------
+::
+ u32 handle
+ int token
+ u32 ratio
+
+Returns
+-------
+OPAL_SUCCESS
+ Success
+
+OPAL_PARAMETER
+ Invalid ratio requested
+
+OPAL_UNSUPPORTED
+ No support for changing the ratio
+
+OPAL_PERMISSION
+ Hardware cannot take the request
+
+OPAL_ASYNC_COMPLETION
+ Request was sent and an async completion message will be sent with
+ token and status of the request.
+
+OPAL_HARDWARE
+ Unable to procced due to the current hardware state
+
+OPAL_BUSY
+ Previous request in progress
+
+OPAL_INTERNAL_ERROR
+ Error in request response
+
+OPAL_TIMEOUT
+ Timeout in request completion
diff --git a/hw/occ.c b/hw/occ.c
index d286628..8337011 100644
--- a/hw/occ.c
+++ b/hw/occ.c
@@ -29,6 +29,7 @@
#include <timer.h>
#include <i2c.h>
#include <powercap.h>
+#include <psr.h>
/* OCC Communication Area for PStates */
@@ -1215,6 +1216,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)
{
@@ -1260,6 +1262,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 */
@@ -1364,6 +1369,96 @@ int occ_set_powercap(u32 handle, 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 */
+};
+
+int occ_get_psr(u32 handle, u32 *ratio)
+{
+ struct occ_dynamic_data *ddata;
+ struct proc_chip *chip;
+ u8 i = psr_get_rid(handle);
+
+ if (psr_get_type(handle) != PSR_TYPE_CPU_TO_GPU)
+ return OPAL_UNSUPPORTED;
+
+ if (i > nr_occs)
+ return OPAL_UNSUPPORTED;
+
+ if (!(*chips[i].valid))
+ return OPAL_HARDWARE;
+
+ 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,
+};
+
+int occ_set_psr(u32 handle, int token, u32 ratio)
+{
+ struct occ_dynamic_data *ddata;
+ struct proc_chip *chip;
+ u8 i = psr_get_rid(handle);
+
+ if (psr_get_type(handle) != PSR_TYPE_CPU_TO_GPU)
+ return OPAL_UNSUPPORTED;
+
+ if (ratio > 100)
+ return OPAL_PARAMETER;
+
+ if (i > nr_occs)
+ return OPAL_UNSUPPORTED;
+
+ if (!(*chips[i].valid))
+ return OPAL_HARDWARE;
+
+ 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;
+ int i;
+
+ node = dt_new(power_mgt, "psr");
+ if (!node) {
+ prerror("OCC: Failed to create power-shifting-ratio node\n");
+ return;
+ }
+
+ dt_add_property_string(node, "compatible",
+ "ibm,opal-power-shift-ratio");
+ for (i = 0; i < nr_occs; i++) {
+ struct dt_node *cnode;
+ char name[20];
+ u32 handle = psr_make_handle(PSR_CLASS_OCC, i,
+ PSR_TYPE_CPU_TO_GPU);
+
+ 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);
+ }
+}
+
/* CPU-OCC PState init */
/* Called after OCC init on P8 and P9 */
void occ_pstates_init(void)
diff --git a/include/opal-api.h b/include/opal-api.h
index 3ad4898..8d33c08 100644
--- a/include/opal-api.h
+++ b/include/opal-api.h
@@ -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_POWER_SHIFT_RATIO 154
+#define OPAL_SET_POWER_SHIFT_RATIO 155
+#define OPAL_LAST 155
/* Device tree flags */
diff --git a/include/psr.h b/include/psr.h
new file mode 100644
index 0000000..92c0aa5
--- /dev/null
+++ b/include/psr.h
@@ -0,0 +1,46 @@
+/* Copyright 2017 IBM 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.
+ */
+
+#ifndef __PSR_H
+#define __PSR_H
+
+#include <opal.h>
+
+enum psr_class {
+ PSR_CLASS_OCC,
+};
+
+/*
+ * PSR handle is defined as u32. The first and last bytes are
+ * used to indicate the class and type. RID indiactes psr class
+ * specific data. For PSR_CLASS_OCC psr class RID is the chip index.
+ *
+ * | Class |Reserved| RID | Type |
+ * |-------|--------|------|------|
+ */
+
+#define psr_make_handle(class, rid, type) (((class & 0xF) << 24) | \
+ ((rid & 0xF) << 8) | (type & 0xF))
+
+#define psr_get_class(handle) ((handle >> 24) & 0xF)
+#define psr_get_rid(handle) ((handle >> 8) & 0xF)
+#define psr_get_type(handle) (handle & 0xF)
+
+/* Powercap OCC interface */
+int occ_get_psr(u32 handle, u32 *ratio);
+int occ_set_psr(u32 handle, int token, u32 ratio);
+
+#endif /* __PSR_H */