aboutsummaryrefslogtreecommitdiff
path: root/src/soc/amd/picasso/root_complex.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/soc/amd/picasso/root_complex.c')
-rw-r--r--src/soc/amd/picasso/root_complex.c89
1 files changed, 89 insertions, 0 deletions
diff --git a/src/soc/amd/picasso/root_complex.c b/src/soc/amd/picasso/root_complex.c
index 21af481732..6c721e17c8 100644
--- a/src/soc/amd/picasso/root_complex.c
+++ b/src/soc/amd/picasso/root_complex.c
@@ -13,7 +13,44 @@
#include <stdint.h>
#include <soc/memmap.h>
#include <soc/iomap.h>
+#include "chip.h"
+enum {
+ ALIB_DPTCI_FUNCTION_ID = 0xc,
+ SUSTAINED_POWER_LIMIT_PARAM_ID = 0x5,
+ FAST_PPT_LIMIT_PARAM_ID = 0x6,
+ SLOW_PPT_LIMIT_PARAM_ID = 0x7,
+ DPTC_TOTAL_UPDATE_PARAMS = 3,
+};
+
+struct dptc_param {
+ uint8_t id;
+ uint32_t value;
+} __packed;
+
+struct dptc_input {
+ uint16_t size;
+ struct dptc_param params[DPTC_TOTAL_UPDATE_PARAMS];
+} __packed;
+
+#define DPTC_INPUTS(_sustained, _fast, _slow) \
+ { \
+ .size = sizeof(struct dptc_input), \
+ .params = { \
+ { \
+ .id = SUSTAINED_POWER_LIMIT_PARAM_ID, \
+ .value = _sustained, \
+ }, \
+ { \
+ .id = FAST_PPT_LIMIT_PARAM_ID, \
+ .value = _fast, \
+ }, \
+ { \
+ .id = SLOW_PPT_LIMIT_PARAM_ID, \
+ .value = _slow, \
+ }, \
+ }, \
+ }
/*
*
* +--------------------------------+
@@ -139,6 +176,57 @@ static void read_resources(struct device *dev)
gnb_apic->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
}
+static void dptc_call_alib(const char *buf_name, uint8_t *buffer, size_t size)
+{
+ /* Name (buf_name, Buffer(size) {...} */
+ acpigen_write_name(buf_name);
+ acpigen_write_byte_buffer(buffer, size);
+
+ /* \_SB.ALIB(0xc, buf_name) */
+ acpigen_emit_namestring("\\_SB.ALIB");
+ acpigen_write_integer(ALIB_DPTCI_FUNCTION_ID);
+ acpigen_emit_namestring(buf_name);
+}
+
+static void acipgen_dptci(void)
+{
+ const config_t *config = config_of_soc();
+
+ if (!config->dptc_enable)
+ return;
+
+ struct dptc_input default_input = DPTC_INPUTS(config->sustained_power_limit,
+ config->fast_ppt_limit,
+ config->slow_ppt_limit);
+ struct dptc_input tablet_mode_input = DPTC_INPUTS(
+ config->sustained_power_limit_tablet_mode,
+ config->fast_ppt_limit_tablet_mode,
+ config->slow_ppt_limit_tablet_mode);
+ /* Scope (\_SB) */
+ acpigen_write_scope("\\_SB");
+
+ /* Method(DPTC, 0, Serialized) */
+ acpigen_write_method_serialized("DPTC", 0);
+
+ /* If (LEqual ("\_SB.PCI0.LPCB.EC0.TBMD", 1)) */
+ acpigen_write_if_lequal_namestr_int("\\_SB.PCI0.LPCB.EC0.TBMD", 1);
+
+ dptc_call_alib("TABB", (uint8_t *)(void *)&tablet_mode_input,
+ sizeof(tablet_mode_input));
+
+ acpigen_pop_len(); /* If */
+
+ /* Else */
+ acpigen_write_else();
+
+ dptc_call_alib("DEFB", (uint8_t *)(void *)&default_input, sizeof(default_input));
+
+ acpigen_pop_len(); /* Else */
+
+ acpigen_pop_len(); /* Method DPTC */
+ acpigen_pop_len(); /* Scope \_SB */
+}
+
/* Used by \_SB.PCI0._CRS */
static void root_complex_fill_ssdt(const struct device *device)
{
@@ -164,6 +252,7 @@ static void root_complex_fill_ssdt(const struct device *device)
*/
acpigen_write_name_dword("TOM2", (msr.hi << 12) | msr.lo >> 20);
acpigen_pop_len();
+ acipgen_dptci();
}
static struct device_operations root_complex_operations = {