aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/device-tree/ibm,opal/power-mgt/powercap.rst9
-rw-r--r--hw/occ.c30
2 files changed, 30 insertions, 9 deletions
diff --git a/doc/device-tree/ibm,opal/power-mgt/powercap.rst b/doc/device-tree/ibm,opal/power-mgt/powercap.rst
index 5a8d007..5d24ee1 100644
--- a/doc/device-tree/ibm,opal/power-mgt/powercap.rst
+++ b/doc/device-tree/ibm,opal/power-mgt/powercap.rst
@@ -20,11 +20,17 @@ Each child node has below properties:
Handle to indicate the current powercap
`powercap-min`
- Minimum possible powercap
+ Absolute minimum possible powercap. This points to the soft powercap minimum
+ limit as exported by OCC. The powercap set in the soft powercap range may or
+ may not be maintained.
`powercap-max`
Maximum possible powercap
+`powercap-hard-min`
+ This value points to the hard minimum powercap limit. The powercap set above
+ this limit is guaranteed unless there is a hardware failure
+
Powercap handle uses the following encoding: ::
| Class | Reserved | Attribute |
@@ -44,6 +50,7 @@ the future.
powercap-current = <0x00000002>;
powercap-min = <0x00000000>;
powercap-max = <0x00000001>;
+ powercap-hard-min = <0x000000003>;
};
};
};
diff --git a/hw/occ.c b/hw/occ.c
index 6b46462..dc39ae1 100644
--- a/hw/occ.c
+++ b/hw/occ.c
@@ -220,9 +220,12 @@ struct occ_response_buffer {
* power to maintain a power cap. Value of 100
* means take all power from CPU.
* @pwr_cap_type: Indicates type of power cap in effect
- * @min_pwr_cap: Minimum allowed system power cap in Watts
+ * @hard_min_pwr_cap: Hard minimum system power cap in Watts.
+ * Guaranteed unless hardware failure
* @max_pwr_cap: Maximum allowed system power cap in Watts
* @cur_pwr_cap: Current system power cap
+ * @soft_min_pwr_cap: Soft powercap minimum. OCC may or may not be
+ * able to maintain this
* @spare/reserved: Unused data
* @cmd: Opal Command Buffer
* @rsp: OCC Response Buffer
@@ -238,10 +241,11 @@ struct occ_dynamic_data {
u8 quick_pwr_drop;
u8 pwr_shifting_ratio;
u8 pwr_cap_type;
- u16 min_pwr_cap;
+ u16 hard_min_pwr_cap;
u16 max_pwr_cap;
u16 cur_pwr_cap;
- u8 pad[112];
+ u16 soft_min_pwr_cap;
+ u8 pad[110];
struct opal_command_buffer cmd;
struct occ_response_buffer rsp;
} __packed;
@@ -1292,9 +1296,10 @@ static void occ_cmd_interface_init(void)
/* Powercap interface */
enum sensor_powercap_occ_attr {
- POWERCAP_OCC_MIN,
+ POWERCAP_OCC_SOFT_MIN,
POWERCAP_OCC_MAX,
POWERCAP_OCC_CUR,
+ POWERCAP_OCC_HARD_MIN,
};
static void occ_add_powercap_sensors(struct dt_node *power_mgt)
@@ -1318,11 +1323,17 @@ static void occ_add_powercap_sensors(struct dt_node *power_mgt)
handle = powercap_make_handle(POWERCAP_CLASS_OCC, POWERCAP_OCC_CUR);
dt_add_property_cells(node, "powercap-current", handle);
- handle = powercap_make_handle(POWERCAP_CLASS_OCC, POWERCAP_OCC_MIN);
+ handle = powercap_make_handle(POWERCAP_CLASS_OCC,
+ POWERCAP_OCC_SOFT_MIN);
dt_add_property_cells(node, "powercap-min", handle);
handle = powercap_make_handle(POWERCAP_CLASS_OCC, POWERCAP_OCC_MAX);
dt_add_property_cells(node, "powercap-max", handle);
+
+ handle = powercap_make_handle(POWERCAP_CLASS_OCC,
+ POWERCAP_OCC_HARD_MIN);
+ dt_add_property_cells(node, "powercap-hard-min", handle);
+
}
int occ_get_powercap(u32 handle, u32 *pcap)
@@ -1339,8 +1350,8 @@ int occ_get_powercap(u32 handle, u32 *pcap)
return OPAL_HARDWARE;
switch (powercap_get_attr(handle)) {
- case POWERCAP_OCC_MIN:
- *pcap = ddata->min_pwr_cap;
+ case POWERCAP_OCC_SOFT_MIN:
+ *pcap = ddata->soft_min_pwr_cap;
break;
case POWERCAP_OCC_MAX:
*pcap = ddata->max_pwr_cap;
@@ -1348,6 +1359,9 @@ int occ_get_powercap(u32 handle, u32 *pcap)
case POWERCAP_OCC_CUR:
*pcap = ddata->cur_pwr_cap;
break;
+ case POWERCAP_OCC_HARD_MIN:
+ *pcap = ddata->hard_min_pwr_cap;
+ break;
default:
*pcap = 0;
return OPAL_UNSUPPORTED;
@@ -1388,7 +1402,7 @@ int occ_set_powercap(u32 handle, int token, u32 pcap)
return OPAL_SUCCESS;
if (pcap && (pcap > ddata->max_pwr_cap ||
- pcap < ddata->min_pwr_cap))
+ pcap < ddata->soft_min_pwr_cap))
return OPAL_PARAMETER;
pcap_cdata = pcap;