Tim Wawrzynczak has uploaded this change for review.

View Change

vendorcode/google/chromeos: Add vendor_dptf_* functions

This patch adds in the rest of the missing pieces from what is in the
static DPTF ASL implementation. Much of it seems written for ChromeOS
systems, making assumptions about \_SB.PCI0.LPCB.EC0.* methods that may
exist on other systems. Seeing also that they were only used for
ChromeOS devices in coreboot, the corresponding generation of the AML
was moved to vendorcode/google/chromeos.

BUG=b:143539650
TEST=compiles

Change-Id: Ib30072d1d0748b31bcab240a0fd0e2f12d34aaa4
Signed-off-by: Tim Wawrzynczak <twawrzynczak@chromium.org>
---
M src/vendorcode/google/chromeos/Makefile.inc
A src/vendorcode/google/chromeos/dptf.c
2 files changed, 308 insertions(+), 0 deletions(-)

git pull ssh://review.coreboot.org:29418/coreboot refs/changes/94/41894/1
diff --git a/src/vendorcode/google/chromeos/Makefile.inc b/src/vendorcode/google/chromeos/Makefile.inc
index fc00374..936a298 100644
--- a/src/vendorcode/google/chromeos/Makefile.inc
+++ b/src/vendorcode/google/chromeos/Makefile.inc
@@ -13,6 +13,7 @@
ramstage-$(CONFIG_USE_SAR) += sar.c
ramstage-$(CONFIG_CHROMEOS_DSM_CALIB) += dsm_calib.c
ramstage-$(CONFIG_TPM_CR50) += cr50_enable_update.c
+ramstage-$(CONFIG_DRIVERS_INTEL_DPTF) += dptf.c

bootblock-y += watchdog.c
verstage-y += watchdog.c
diff --git a/src/vendorcode/google/chromeos/dptf.c b/src/vendorcode/google/chromeos/dptf.c
new file mode 100644
index 0000000..cbf7b48
--- /dev/null
+++ b/src/vendorcode/google/chromeos/dptf.c
@@ -0,0 +1,307 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <acpi/acpigen.h>
+#include <acpi/acpigen_dptf.h>
+#include <device/device.h>
+
+/* DPTF Event types */
+enum {
+ TRIP_POINTS_CHANGED_EVENT = 0x81,
+ THERMAL_EVENT = 0x90,
+};
+
+/* EC constants */
+enum {
+ EC_FAN_DUTY_AUTO = 0xFF,
+};
+
+static void write_charger_PPPC(void)
+{
+ acpigen_write_method_serialized("PPPC", 0);
+
+ /*
+ * Convert size of PPSS table to index
+ *
+ * Store (SizeOf (PPSS), Local0)
+ * Decrement (Local0)
+ */
+ acpigen_write_store();
+ acpigen_emit_byte(SIZEOF_OP);
+ acpigen_emit_namestring("PPSS");
+ acpigen_emit_byte(LOCAL0_OP);
+ acpigen_emit_byte(DECREMENT_OP);
+ acpigen_emit_byte(LOCAL0_OP);
+
+ /*
+ * Check if charging is disabled (AC removed)
+ *
+ * If (\_SB.PCI0.LPCB.EC0.ACEX () = Zero) {
+ * Return (Local0)
+ * }
+ */
+ acpigen_write_if();
+ acpigen_emit_byte(LEQUAL_OP);
+ acpigen_emit_namestring("\\_SB.PCI0.LPCB.EC0.ACEX");
+ acpigen_emit_byte(ZERO_OP);
+ acpigen_emit_byte(RETURN_OP);
+ acpigen_emit_byte(LOCAL0_OP);
+ acpigen_pop_len(); /* If */
+
+ /*
+ * Return highest power state
+ *
+ * Return (0)
+ */
+ acpigen_emit_byte(RETURN_OP);
+ acpigen_emit_byte(ZERO_OP);
+
+ acpigen_pop_len(); /* Method */
+}
+
+static void write_charger_SPPC(void)
+{
+ /*
+ * SPPC - Set charger current limit
+ * Method(SPPC, 1) {
+ * Store (DeRefOf (Index (DeRefOf (Index
+ * (PPSS, ToInteger (Arg0))), 4)), Local0)
+ * \_SB.PCI0.LPCB.EC0.CHGS (Local0)
+ * }
+ */
+
+ acpigen_write_method_serialized("SPPC", 1);
+
+ /* Retrieve Control (index 4) for specified PPSS level */
+ acpigen_emit_byte(STORE_OP);
+ acpigen_emit_byte(DEREF_OP);
+ acpigen_emit_byte(INDEX_OP);
+ acpigen_emit_byte(DEREF_OP);
+ acpigen_emit_byte(INDEX_OP);
+ acpigen_emit_namestring("PPSS");
+ acpigen_write_to_integer(ARG0_OP, ZERO_OP);
+ acpigen_emit_byte(ZERO_OP); /* 3rd arg to Index */
+ acpigen_write_integer(4); /* Index */
+ acpigen_emit_byte(ZERO_OP); /* 3rd arg to Index */
+ acpigen_emit_byte(LOCAL0_OP);
+
+ /* Pass Control value to EC to limit charging */
+ acpigen_emit_namestring("\\_SB.PCI0.LPCB.EC0.CHGS");
+ acpigen_emit_byte(LOCAL0_OP);
+ acpigen_pop_len(); /* Method */
+}
+
+static void write_fan_fst(void)
+{
+ /* TFST is a package that is used to store data from FAND */
+ acpigen_write_name("TFST");
+ acpigen_write_package(3);
+ acpigen_write_integer(0); /* Revision */
+ acpigen_write_integer(0); /* Control */
+ acpigen_write_integer(0); /* Speed */
+ acpigen_pop_len(); /* Package */
+
+ /* _FST */
+ acpigen_write_method_serialized("_FST", 0);
+ acpigen_write_store();
+ acpigen_emit_namestring("\\_SB.PCI0.LPCB.EC0.FAND");
+ acpigen_emit_byte(INDEX_OP);
+ acpigen_emit_namestring("TFST");
+ acpigen_write_integer(1);
+ acpigen_emit_byte(ZERO_OP); /* 3rd arg to Index */
+ acpigen_emit_byte(RETURN_OP);
+ acpigen_emit_namestring("TFST");
+ acpigen_pop_len(); /* Method _FST */
+}
+
+static void write_fan_fsl(void)
+{
+ /* _FSL */
+ acpigen_write_method_serialized("_FSL", 1);
+ acpigen_write_store();
+ acpigen_emit_byte(ARG0_OP);
+ acpigen_emit_namestring("\\_SB.PCI0.LPCB.EC0.FAND");
+ acpigen_pop_len(); /* Method _FSL */
+}
+
+/* Note: requires manual insertion of acpigen_pop_len() for the If */
+static void write_is_policy_enabled(unsigned int index, bool enabled)
+{
+ /*
+ * If (And (LEqual (Deref (Index (IDSP, index)), Arg0))
+ * (LEqual (Arg1, enabled)))
+ */
+ acpigen_write_if();
+ acpigen_emit_byte(LAND_OP);
+ acpigen_emit_byte(LEQUAL_OP);
+ acpigen_emit_byte(DEREF_OP);
+ acpigen_emit_byte(INDEX_OP);
+ acpigen_emit_namestring("IDSP");
+ acpigen_write_integer(index);
+ acpigen_emit_byte(ZERO_OP); /* 3rd arg of index - unused */
+ acpigen_emit_byte(ARG0_OP); /* end lequal */
+ acpigen_emit_byte(LEQUAL_OP);
+ acpigen_emit_byte(ARG1_OP);
+ acpigen_write_integer(enabled ? 1 : 0);
+}
+
+static void write_dptf_OSC(bool active_policy_enabled)
+{
+ /*
+ * Arg0: Buffer containing UUID
+ * Arg1: "Integer containing Revision ID of buffer format", but Linux passes whether
+ * it is enabling (1) or disabling (0) the policy in Arg1.
+ * Arg2: Integer containing count of entries in Arg3
+ * Arg3: Buffer containing list of DWORD capabilities
+ * Return: Buffer containing list of DWORD capabilities
+ */
+ acpigen_write_method_serialized("_OSC", 4);
+
+ /* Is the OS passing us the Passive Policy? */
+ write_is_policy_enabled(0, true);
+ acpigen_emit_namestring("^TINI");
+ acpigen_emit_namestring("^TCHG.INIT");
+ acpigen_pop_len(); /* If */
+
+ /* If the Active Policy is disabled, disable DPTF fan control in the EC */
+ if (active_policy_enabled) {
+ write_is_policy_enabled(2, false);
+ acpigen_write_store();
+ acpigen_write_integer(EC_FAN_DUTY_AUTO);
+ acpigen_emit_namestring("\\_SB.PCI0.LPCB.EC0.FAND");
+ acpigen_pop_len(); /* If */
+ }
+
+ acpigen_emit_byte(RETURN_OP);
+ acpigen_emit_byte(ARG3_OP);
+ acpigen_pop_len(); /* Method _OSC */
+}
+
+void vendor_dptf_write_dppm_methods(bool active_policy_enabled, bool tsr_en[4])
+{
+ enum dptf_participant p;
+ char name[16];
+ int i;
+
+ acpigen_write_scope("\\_SB.DPTF");
+ write_dptf_OSC(active_policy_enabled);
+
+ /* TEVT */
+ if (CONFIG(EC_SUPPORTS_DPTF_TEVT)) {
+ acpigen_write_method("TEVT", 0);
+
+ /* Local0 = ToInteger(Arg0) */
+ acpigen_write_to_integer(ARG0_OP, LOCAL0_OP);
+ for (p = DPTF_TSR0, i = 0; p <= DPTF_TSR3; ++p, ++i) {
+ if (!tsr_en[i])
+ continue;
+
+ snprintf(name, sizeof(name), "^TSR%1d", i);
+
+ /* If (Local0 = i) Notify (TSRx, 0x90) */
+ acpigen_write_if();
+ acpigen_emit_byte(LEQUAL_OP);
+ acpigen_emit_byte(LOCAL0_OP);
+ acpigen_write_integer(i); /* TMPI */
+ acpigen_emit_byte(NOTIFY_OP);
+ acpigen_emit_namestring(name);
+ acpigen_write_integer(THERMAL_EVENT);
+ acpigen_pop_len(); /* If */
+ }
+
+ acpigen_pop_len(); /* Method */
+ }
+
+ /* TINI */
+ acpigen_write_method("TINI", 0);
+ for (i = 0; i < DPTF_MAX_TSR; ++i) {
+ if (!tsr_en[i])
+ continue;
+ snprintf(name, sizeof(name), "^TSR%1d.PATD", i);
+ acpigen_emit_namestring(name);
+ }
+
+ acpigen_pop_len(); /* Method */
+
+ /* TPET */
+ acpigen_write_method("TPET", 0);
+ for (p = DPTF_TSR0, i = 0; p <= DPTF_TSR3; ++p, ++i) {
+ if (!tsr_en[i])
+ continue;
+
+ snprintf(name, sizeof(name), "^TSR%1d", i);
+ acpigen_emit_byte(NOTIFY_OP);
+ acpigen_emit_namestring(name);
+ acpigen_write_integer(TRIP_POINTS_CHANGED_EVENT);
+ }
+
+ acpigen_pop_len(); /* Method */
+ acpigen_pop_len(); /* Scope */
+}
+
+static void write_charger_init(void)
+{
+ /* Initialize charger participant */
+ acpigen_write_method_serialized("INIT", 0);
+
+ /* Disable charge limit */
+ acpigen_emit_namestring("\\_SB.PCI0.LPCB.EC0.CHGD");
+ acpigen_pop_len(); /* Method */
+}
+
+void vendor_dptf_write_charger_methods(void)
+{
+ dptf_write_scope(DPTF_CHARGER);
+
+ write_charger_PPPC();
+ write_charger_SPPC();
+ write_charger_init();
+
+ acpigen_pop_len(); /* Scope */
+}
+
+void vendor_dptf_write_fan_methods(void)
+{
+ dptf_write_scope(DPTF_FAN);
+
+ write_fan_fsl();
+ write_fan_fst();
+
+ acpigen_pop_len(); /* Scope */
+}
+
+void vendor_dptf_write_thermal_methods(int tsr_index)
+{
+ dptf_write_scope((enum dptf_participant)(DPTF_TSR0 + tsr_index));
+
+ /* _TMP - read temperature from EC */
+ acpigen_write_method_serialized("_TMP", 0);
+ acpigen_emit_byte(RETURN_OP);
+ acpigen_emit_namestring("\\_SB.PCI0.LPCB.EC0.TSRD");
+ acpigen_emit_namestring("TMPI");
+ acpigen_pop_len(); /* Method _TMP */
+
+ /* PATC - Aux trip point count */
+ acpigen_write_name_integer("PATC", 2);
+
+ /* PAT0 - Set Aux trip point 0 */
+ acpigen_write_method_serialized("PAT0", 1);
+ acpigen_emit_namestring("\\_SB.PCI0.LPCB.EC0.PAT0");
+ acpigen_emit_namestring("TMPI");
+ acpigen_emit_byte(ARG0_OP);
+ acpigen_pop_len(); /* Method PAT0 */
+
+ /* PAT1 - Set Aux trip point 1 */
+ acpigen_write_method_serialized("PAT1", 1);
+ acpigen_emit_namestring("\\_SB.PCI0.LPCB.EC0.PAT1");
+ acpigen_emit_namestring("TMPI");
+ acpigen_emit_byte(ARG0_OP);
+ acpigen_pop_len(); /* Method PAT0 */
+
+ /* PATD - Disable Aux trip point */
+ acpigen_write_method_serialized("PATD", 0);
+ acpigen_emit_namestring("\\_SB.PCI0.LPCB.EC0.PATD");
+ acpigen_emit_namestring("TMPI");
+ acpigen_pop_len(); /* Method PAT0 */
+
+ acpigen_pop_len(); /* Scope */
+}

To view, visit change 41894. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-Change-Id: Ib30072d1d0748b31bcab240a0fd0e2f12d34aaa4
Gerrit-Change-Number: 41894
Gerrit-PatchSet: 1
Gerrit-Owner: Tim Wawrzynczak <twawrzynczak@chromium.org>
Gerrit-Reviewer: Martin Roth <martinroth@google.com>
Gerrit-Reviewer: Patrick Georgi <pgeorgi@google.com>
Gerrit-MessageType: newchange