diff options
-rw-r--r-- | src/soc/amd/picasso/chip.h | 8 | ||||
-rw-r--r-- | src/soc/amd/picasso/root_complex.c | 89 |
2 files changed, 97 insertions, 0 deletions
diff --git a/src/soc/amd/picasso/chip.h b/src/soc/amd/picasso/chip.h index e3da2553b9..11675097cf 100644 --- a/src/soc/amd/picasso/chip.h +++ b/src/soc/amd/picasso/chip.h @@ -90,6 +90,14 @@ struct soc_amd_picasso_config { uint32_t stapm_time_constant; uint32_t sustained_power_limit; + /* Enable dptc for tablet mode (0 = disable, 1 = enable) */ + uint8_t dptc_enable; + + /* STAPM Configuration for tablet mode (need enable dptc_enable first) */ + uint32_t fast_ppt_limit_tablet_mode; + uint32_t slow_ppt_limit_tablet_mode; + uint32_t sustained_power_limit_tablet_mode; + /* PROCHOT_L de-assertion Ramp Time */ uint32_t prochot_l_deassertion_ramp_time; 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 = { |