soc/amd: Refactor DPTC Tablet Mode

Refactor AMD DPTC tablet mode in preparation for adding low/no battery
DPTC settings.

1. Refactor and simplify acpigen_write_alib_dptc() into the following
   functions:
   - acpigen_write_alib_dptc_default()
   - acpigen_write_alib_dptc_tablet()
2. Add device tree register value dptc_tablet_mode_enable to control
   whether DPTC tablet mode is enabled for a variant.
3. Add dptc.asl to perform the necessary ACPI checking before modifying
   the DPTC settings.

BRANCH=none
BUG=b:217911928
TEST=Build zork
TEST=Build nipperkin
TEST=Boot skyrim

Change-Id: I2518fdd526868c9d5668a6018fd3570392e809c0
Signed-off-by: Tim Van Patten <timvp@google.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/66994
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Karthik Ramasubramanian <kramasub@google.com>
diff --git a/src/soc/amd/cezanne/acpi/soc.asl b/src/soc/amd/cezanne/acpi/soc.asl
index bf2838a..7e3a3ee 100644
--- a/src/soc/amd/cezanne/acpi/soc.asl
+++ b/src/soc/amd/cezanne/acpi/soc.asl
@@ -27,10 +27,12 @@
 
 #include <soc/amd/common/acpi/upep.asl>
 
+#include <soc/amd/common/acpi/dptc.asl>
+
 #include "rtc_workaround.asl"
 
 /*
- * Platform Wake Notify
+ * Platform Notify
  *
  * This is called by soc/amd/common/acpi/platform.asl.
  */
diff --git a/src/soc/amd/cezanne/chip.h b/src/soc/amd/cezanne/chip.h
index ab798be..74f60ff 100644
--- a/src/soc/amd/cezanne/chip.h
+++ b/src/soc/amd/cezanne/chip.h
@@ -86,10 +86,10 @@
 	uint32_t telemetry_vddcrsocfull_scale_current_mA;
 	uint32_t telemetry_vddcrsocoffset;
 
-	/* Enable dptc for tablet mode */
-	bool dptc_enable;
+	/* Enable dptc tablet mode */
+	bool dptc_tablet_mode_enable;
 
-	/* STAPM Configuration for tablet mode (need enable dptc_enable first) */
+	/* STAPM Configuration for tablet mode */
 	uint32_t fast_ppt_limit_tablet_mode_mW;
 	uint32_t slow_ppt_limit_tablet_mode_mW;
 	uint32_t sustained_power_limit_tablet_mode_mW;
diff --git a/src/soc/amd/cezanne/root_complex.c b/src/soc/amd/cezanne/root_complex.c
index 075f1a1f..c67a6f7 100644
--- a/src/soc/amd/cezanne/root_complex.c
+++ b/src/soc/amd/cezanne/root_complex.c
@@ -186,21 +186,24 @@
 {
 	const struct soc_amd_cezanne_config *config = config_of_soc();
 
-	if (!config->dptc_enable)
+	if (!config->dptc_tablet_mode_enable)
 		return;
 
+	/* DPTC is enabled. Always fill out the default DPTC values. */
 	struct dptc_input default_input = DPTC_INPUTS(config->thermctl_limit_degreeC,
-					config->sustained_power_limit_mW,
-					config->fast_ppt_limit_mW,
-					config->slow_ppt_limit_mW);
+		config->sustained_power_limit_mW,
+		config->fast_ppt_limit_mW,
+		config->slow_ppt_limit_mW);
+	acpigen_write_alib_dptc_default((uint8_t *)&default_input, sizeof(default_input));
+
+	/* Tablet Mode */
 	struct dptc_input tablet_mode_input = DPTC_INPUTS(
 					config->thermctl_limit_tablet_mode_degreeC,
 					config->sustained_power_limit_tablet_mode_mW,
 					config->fast_ppt_limit_tablet_mode_mW,
 					config->slow_ppt_limit_tablet_mode_mW);
-
-	acpigen_write_alib_dptc((uint8_t *)&default_input, sizeof(default_input),
-		(uint8_t *)&tablet_mode_input, sizeof(tablet_mode_input));
+	acpigen_write_alib_dptc_tablet((uint8_t *)&tablet_mode_input,
+		sizeof(tablet_mode_input));
 }
 
 static void root_complex_fill_ssdt(const struct device *device)
diff --git a/src/soc/amd/common/acpi/dptc.asl b/src/soc/amd/common/acpi/dptc.asl
new file mode 100644
index 0000000..611024c
--- /dev/null
+++ b/src/soc/amd/common/acpi/dptc.asl
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+External(\_SB.DDEF, MethodObj)
+External(\_SB.DTAB, MethodObj)
+
+Scope (\_SB)
+{
+    Method (DPTC, 0, Serialized)
+    {
+        /* If _SB.DDEF is not present, DPTC is not enabled so return early. */
+        If (!CondRefOf (\_SB.DDEF))
+        {
+            Return (Zero)
+        }
+
+        If (CondRefOf (\_SB.DTAB) && (\_SB.PCI0.LPCB.EC0.TBMD == One))
+        {
+            \_SB.DTAB()
+            Return (Zero)
+        }
+
+        \_SB.DDEF()
+        Return (Zero)
+    }
+}
diff --git a/src/soc/amd/common/block/acpi/alib.c b/src/soc/amd/common/block/acpi/alib.c
index 7dbb9b8..4f6eafb 100644
--- a/src/soc/amd/common/block/acpi/alib.c
+++ b/src/soc/amd/common/block/acpi/alib.c
@@ -16,28 +16,60 @@
 	acpigen_emit_namestring(buf_name);
 }
 
-void acpigen_write_alib_dptc(uint8_t *default_param, size_t default_param_len,
-	uint8_t *tablet_param, size_t tablet_param_len)
+void acpigen_write_alib_dptc_default(uint8_t *default_param, size_t default_param_len)
 {
 	/* Scope (\_SB) */
 	acpigen_write_scope("\\_SB");
 
-	/* Method(DPTC, 0, Serialized) */
-	acpigen_write_method_serialized("DPTC", 0);
-
-	/* TODO: The code assumes that if DPTC gets called the following object exists */
-	/* If (LEqual ("\_SB.PCI0.LPCB.EC0.TBMD", 1)) */
-	acpigen_write_if_lequal_namestr_int("\\_SB.PCI0.LPCB.EC0.TBMD", 1);
-
-	acpigen_dptc_call_alib("TABB", tablet_param, tablet_param_len);
-
-	/* Else */
-	acpigen_write_else();
-
+	/* Default (Unthrottled) Mode */
+	/* Scope (\_SB)
+	 * {
+	 *     Method (DDEF, 0, Serialized)
+	 *     {
+	 *         Debug = "DPTC: Using normal SOC DPTC Settings."
+	 *         Name (DEFB, Buffer (0x25)
+	 *         {
+	 *             ...
+	 *         })
+	 *         \_SB.ALIB
+	 *         0x0C
+	 *         DEFB
+	 *     }
+	 * }
+	 */
+	acpigen_write_method_serialized("DDEF", 0);
+	acpigen_write_debug_string("DPTC: Using normal SOC DPTC Settings.");
 	acpigen_dptc_call_alib("DEFB", default_param, default_param_len);
+	acpigen_write_method_end();
 
-	acpigen_pop_len(); /* Else */
+	acpigen_write_scope_end();
+}
 
-	acpigen_pop_len(); /* Method DPTC */
-	acpigen_pop_len(); /* Scope \_SB */
+void acpigen_write_alib_dptc_tablet(uint8_t *tablet_param, size_t tablet_param_len)
+{
+	/* Scope (\_SB) */
+	acpigen_write_scope("\\_SB");
+
+	/* Tablet Mode */
+	/* Scope (\_SB)
+	 * {
+	 *     Method (DTAB, 0, Serialized)
+	 *     {
+	 *         Debug = "DPTC: Using tablet mode SOC DPTC Settings."
+	 *         Name (TABB, Buffer (0x25)
+	 *         {
+	 *             ...
+	 *         })
+	 *         \_SB.ALIB
+	 *         0x0C
+	 *         TABB
+	 *     }
+	 * }
+	 */
+	acpigen_write_method_serialized("DTAB", 0);
+	acpigen_write_debug_string("DPTC: Using tablet mode SOC DPTC Settings.");
+	acpigen_dptc_call_alib("TABB", tablet_param, tablet_param_len);
+	acpigen_write_method_end();
+
+	acpigen_write_scope_end();
 }
diff --git a/src/soc/amd/common/block/include/amdblocks/alib.h b/src/soc/amd/common/block/include/amdblocks/alib.h
index 8899c78..6e19366 100644
--- a/src/soc/amd/common/block/include/amdblocks/alib.h
+++ b/src/soc/amd/common/block/include/amdblocks/alib.h
@@ -27,8 +27,8 @@
 	uint32_t value;
 } __packed;
 
-void acpigen_write_alib_dptc(uint8_t *default_param, size_t default_param_len,
-	uint8_t *tablet_param, size_t tablet_param_len);
+void acpigen_write_alib_dptc_default(uint8_t *default_param, size_t default_param_len);
+void acpigen_write_alib_dptc_tablet(uint8_t *tablet_param, size_t tablet_param_len);
 
 #endif /* !__ACPI__ */
 
diff --git a/src/soc/amd/mendocino/Kconfig b/src/soc/amd/mendocino/Kconfig
index d0ce78b..7155aab 100644
--- a/src/soc/amd/mendocino/Kconfig
+++ b/src/soc/amd/mendocino/Kconfig
@@ -52,7 +52,7 @@
 	select SOC_AMD_COMMON_BLOCK_ACP_GEN2
 	select SOC_AMD_COMMON_BLOCK_ACPI	# TODO: Check if this is still correct
 	select SOC_AMD_COMMON_BLOCK_ACPIMMIO
-	select SOC_AMD_COMMON_BLOCK_ACPI_ALIB	# TODO: Check if this is still correct
+	select SOC_AMD_COMMON_BLOCK_ACPI_ALIB
 	select SOC_AMD_COMMON_BLOCK_ACPI_CPPC
 	select SOC_AMD_COMMON_BLOCK_ACPI_GPIO
 	select SOC_AMD_COMMON_BLOCK_ACPI_IVRS	# TODO: Check if this is still correct
diff --git a/src/soc/amd/mendocino/acpi/soc.asl b/src/soc/amd/mendocino/acpi/soc.asl
index f5a41a1..5bce314 100644
--- a/src/soc/amd/mendocino/acpi/soc.asl
+++ b/src/soc/amd/mendocino/acpi/soc.asl
@@ -29,10 +29,12 @@
 
 #include <soc/amd/common/acpi/upep.asl>
 
+#include <soc/amd/common/acpi/dptc.asl>
+
 #include "rtc_workaround.asl"
 
 /*
- * Platform Wake Notify
+ * Platform Notify
  *
  * This is called by soc/amd/common/acpi/platform.asl.
  */
diff --git a/src/soc/amd/mendocino/chip.h b/src/soc/amd/mendocino/chip.h
index a1e4eb9..654294d 100644
--- a/src/soc/amd/mendocino/chip.h
+++ b/src/soc/amd/mendocino/chip.h
@@ -82,10 +82,10 @@
 	uint32_t telemetry_vddcrsocfull_scale_current_mA;
 	uint32_t telemetry_vddcrsocoffset;
 
-	/* Enable dptc for tablet mode */
-	bool dptc_enable;
+	/* Enable dptc tablet mode */
+	bool dptc_tablet_mode_enable;
 
-	/* STAPM Configuration for tablet mode (need enable dptc_enable first) */
+	/* STAPM Configuration for tablet mode */
 	uint32_t fast_ppt_limit_tablet_mode_mW;
 	uint32_t slow_ppt_limit_tablet_mode_mW;
 	uint32_t sustained_power_limit_tablet_mode_mW;
diff --git a/src/soc/amd/mendocino/root_complex.c b/src/soc/amd/mendocino/root_complex.c
index a5371f2..8d15feb 100644
--- a/src/soc/amd/mendocino/root_complex.c
+++ b/src/soc/amd/mendocino/root_complex.c
@@ -188,21 +188,24 @@
 {
 	const struct soc_amd_mendocino_config *config = config_of_soc();
 
-	if (!config->dptc_enable)
+	if (!config->dptc_tablet_mode_enable)
 		return;
 
+	/* DPTC is enabled. Always fill out the default DPTC values. */
 	struct dptc_input default_input = DPTC_INPUTS(config->thermctl_limit_degreeC,
-					config->sustained_power_limit_mW,
-					config->fast_ppt_limit_mW,
-					config->slow_ppt_limit_mW);
+		config->sustained_power_limit_mW,
+		config->fast_ppt_limit_mW,
+		config->slow_ppt_limit_mW);
+	acpigen_write_alib_dptc_default((uint8_t *)&default_input, sizeof(default_input));
+
+	/* Tablet Mode */
 	struct dptc_input tablet_mode_input = DPTC_INPUTS(
 					config->thermctl_limit_tablet_mode_degreeC,
 					config->sustained_power_limit_tablet_mode_mW,
 					config->fast_ppt_limit_tablet_mode_mW,
 					config->slow_ppt_limit_tablet_mode_mW);
-
-	acpigen_write_alib_dptc((uint8_t *)&default_input, sizeof(default_input),
-		(uint8_t *)&tablet_mode_input, sizeof(tablet_mode_input));
+	acpigen_write_alib_dptc_tablet((uint8_t *)&tablet_mode_input,
+		sizeof(tablet_mode_input));
 }
 
 static void root_complex_fill_ssdt(const struct device *device)
diff --git a/src/soc/amd/picasso/acpi/soc.asl b/src/soc/amd/picasso/acpi/soc.asl
index e8c78e1..d9d40c7 100644
--- a/src/soc/amd/picasso/acpi/soc.asl
+++ b/src/soc/amd/picasso/acpi/soc.asl
@@ -16,3 +16,5 @@
 
 /* Add GPIO library */
 #include <soc/amd/common/acpi/gpio_bank_lib.asl>
+
+#include <soc/amd/common/acpi/dptc.asl>
diff --git a/src/soc/amd/picasso/chip.h b/src/soc/amd/picasso/chip.h
index dbf0339..7ff36fc 100644
--- a/src/soc/amd/picasso/chip.h
+++ b/src/soc/amd/picasso/chip.h
@@ -117,10 +117,10 @@
 	uint32_t stapm_time_constant_s;
 	uint32_t sustained_power_limit_mW;
 
-	/* Enable dptc for tablet mode */
-	bool dptc_enable;
+	/* Enable dptc tablet mode */
+	bool dptc_tablet_mode_enable;
 
-	/* STAPM Configuration for tablet mode (need enable dptc_enable first) */
+	/* STAPM Configuration for tablet mode */
 	uint32_t fast_ppt_limit_tablet_mode_mW;
 	uint32_t slow_ppt_limit_tablet_mode_mW;
 	uint32_t sustained_power_limit_tablet_mode_mW;
diff --git a/src/soc/amd/picasso/root_complex.c b/src/soc/amd/picasso/root_complex.c
index ccf1c45..afa8565 100644
--- a/src/soc/amd/picasso/root_complex.c
+++ b/src/soc/amd/picasso/root_complex.c
@@ -184,21 +184,24 @@
 {
 	const struct soc_amd_picasso_config *config = config_of_soc();
 
-	if (!config->dptc_enable)
+	if (!config->dptc_tablet_mode_enable)
 		return;
 
+	/* DPTC is enabled. Always fill out the default DPTC values. */
 	struct dptc_input default_input = DPTC_INPUTS(config->thermctl_limit_degreeC,
 							config->sustained_power_limit_mW,
 							config->fast_ppt_limit_mW,
 							config->slow_ppt_limit_mW);
+	acpigen_write_alib_dptc_default((uint8_t *)&default_input, sizeof(default_input));
+
+	/* Tablet Mode */
 	struct dptc_input tablet_mode_input = DPTC_INPUTS(
 					config->thermctl_limit_tablet_mode_degreeC,
 					config->sustained_power_limit_tablet_mode_mW,
 					config->fast_ppt_limit_tablet_mode_mW,
 					config->slow_ppt_limit_tablet_mode_mW);
-
-	acpigen_write_alib_dptc((uint8_t *)&default_input, sizeof(default_input),
-		(uint8_t *)&tablet_mode_input, sizeof(tablet_mode_input));
+	acpigen_write_alib_dptc_tablet((uint8_t *)&tablet_mode_input,
+		sizeof(tablet_mode_input));
 }
 
 static void root_complex_fill_ssdt(const struct device *device)