From patchwork Mon Jul 27 03:44:58 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1336634 X-Patchwork-Delegate: bmeng.cn@gmail.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=Qo2MgYjM; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4BFQpy5qprz9sPB for ; Mon, 27 Jul 2020 13:51:54 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 166928233D; Mon, 27 Jul 2020 05:48:50 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="Qo2MgYjM"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 87B7D8232C; Mon, 27 Jul 2020 05:46:30 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,SPF_HELO_NONE,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-oi1-x242.google.com (mail-oi1-x242.google.com [IPv6:2607:f8b0:4864:20::242]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 10968822F9 for ; Mon, 27 Jul 2020 05:46:05 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-oi1-x242.google.com with SMTP id y22so13178984oie.8 for ; Sun, 26 Jul 2020 20:46:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=ToFrLrZ3sFH26XQUeViie/jG53R2+FOfKMOiKbLmdWs=; b=Qo2MgYjMhnB6HYxq+CHH2E2xhkc6/6uUWJTKTd7MmzRdWoxKvmbVBj8YFQ/hARLTHa QnJFbixEm69WeRsRDEPP/8vWdwvnCJCxkzCwG1Qjo6XkMFi8TKnSiRSFJUAdzOIGCUZo HDpQbOgpzsqaK+EUWT+ySVAqUHDB5mx6xLvkE= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=ToFrLrZ3sFH26XQUeViie/jG53R2+FOfKMOiKbLmdWs=; b=ExCSYKBs3WP3+574aY9f3MYnWHq1Zg5lo4lIzRntIgU2R3MSUXVA7mcxX9kdo0E/2C dygzyaMF40iuVerFxEnH2W38wCgnQ3M1fiXybBmSFzkw9NNN6Itx6dXP7zHaPVZCGmBT W0lBOUtabWOgkm1AoWJZG2+cd9tBFYkwQ5A9DQ2JKN4mDD0Vzn5HV0hhhq/WdyEUp12e yex7vq/ef/v7PXmXQ4BdLsLxQFMqdRaNRWkhzLw9N3CzQPTkNIe5KrtyFzaNtVI1l6yN /p2hf1ZU44+knk1qvQEJRdlbzSHAOd+Ij0eE7rnMHWIb6GNXSeB+uodYdAXRO564Zpp3 VjUQ== X-Gm-Message-State: AOAM530xlS9wt3fgBmr4ShXtdc80+ywou1NJ2xvtmg60zvD8UKSHhDzP p/vJ5+EviMyHOTTkCcvaI8SlwgKowrX5gA== X-Google-Smtp-Source: ABdhPJz55ngevUD2jOnutzQ7jsQMjL4DJUCz3KWq8Gulzwl8w3ElutcqwIIIMF1rPN5onV6bosjmPg== X-Received: by 2002:aca:56ca:: with SMTP id k193mr202359oib.61.1595821563426; Sun, 26 Jul 2020 20:46:03 -0700 (PDT) Received: from localhost.localdomain (c-73-14-175-90.hsd1.co.comcast.net. [73.14.175.90]) by smtp.gmail.com with ESMTPSA id p64sm1808996oih.39.2020.07.26.20.46.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 26 Jul 2020 20:46:03 -0700 (PDT) From: Simon Glass To: U-Boot Mailing List Cc: Wolfgang Wallner , Bin Meng , Simon Glass Subject: [PATCH v1 26/54] acpi: Add more support for generating processor tables Date: Sun, 26 Jul 2020 21:44:58 -0600 Message-Id: <20200727034526.1461514-10-sjg@chromium.org> X-Mailer: git-send-email 2.28.0.rc0.142.g3c755180ce-goog In-Reply-To: <20200727034526.1461514-1-sjg@chromium.org> References: <20200727034526.1461514-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.34 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.102.3 at phobos.denx.de X-Virus-Status: Clean This adds tables relating to P-States and C-States. Signed-off-by: Simon Glass --- include/acpi/acpigen.h | 162 +++++++++++++++++++++++ lib/acpi/acpigen.c | 167 +++++++++++++++++++++++ test/dm/acpigen.c | 294 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 623 insertions(+) diff --git a/include/acpi/acpigen.h b/include/acpi/acpigen.h index 3a2c6339d5e..976f4dbb9af 100644 --- a/include/acpi/acpigen.h +++ b/include/acpi/acpigen.h @@ -10,8 +10,10 @@ #ifndef __ACPI_ACPIGEN_H #define __ACPI_ACPIGEN_H +#include #include +struct acpi_cstate; struct acpi_ctx; struct acpi_gen_regaddr; struct acpi_gpio; @@ -87,6 +89,53 @@ enum psd_coord { HW_ALL = 0xfe }; +/** + * enum csd_coord - Coordination types for C-states + * + * The type of coordination that exists (hardware) or is required (software) as + * a result of the underlying hardware dependency + */ +enum csd_coord { + CSD_HW_ALL = 0xfe, +}; + +/** + * struct acpi_cstate - Information about a C-State + * + * @ctype: C State type (1=C1, 2=C2, 3=C3) + * @latency: Worst-case latency to enter and exit the C State (in uS) + * @power: Average power consumption of the processor when in this C-State (mW) + * @resource: Register to read to place the processor in this state + */ +struct acpi_cstate { + uint ctype; + uint latency; + uint power; + struct acpi_gen_regaddr resource; +}; + +/** + * struct acpi_tstate - Information about a Throttling Supported State + * + * See ACPI v6.3 section 8.4.5.2: _TSS (Throttling Supported States) + * + * @percent: Percent of the core CPU operating frequency that will be + * available when this throttling state is invoked + * @power: Throttling state’s maximum power dissipation (mw) + * @latency: Worst-case latency (uS) that the CPU is unavailable during a + * transition from any throttling state to this throttling state + * @control: Value to be written to the Processor Control Register + * (THROTTLE_CTRL) to initiate a transition to this throttling state + * @status: Value in THROTTLE_STATUS when in this state + */ +struct acpi_tstate { + uint percent; + uint power; + uint latency; + uint control; + uint status; +}; + /** * acpigen_get_current() - Get the current ACPI code output pointer * @@ -816,4 +865,117 @@ void acpigen_write_processor_package(struct acpi_ctx *ctx, const char *name, */ void acpigen_write_processor_cnot(struct acpi_ctx *ctx, const uint num_cores); +/** + * acpigen_write_ppc() - generates a function returning max P-states + * + * @ctx: ACPI context pointer + * @num_pstates: Number of pstates to return + */ +void acpigen_write_ppc(struct acpi_ctx *ctx, uint num_pstates); + +/** + * acpigen_write_ppc() - generates a function returning PPCM + * + * This returns the maximum number of supported P-states, as saved in the + * variable PPCM + * + * @ctx: ACPI context pointer + */ +void acpigen_write_ppc_nvs(struct acpi_ctx *ctx); + +/** + * acpigen_write_tpc() - Write a _TPC method that returns the TPC limit + * + * @ctx: ACPI context pointer + * @gnvs_tpc_limit: Variable that holds the TPC limit + */ +void acpigen_write_tpc(struct acpi_ctx *ctx, const char *gnvs_tpc_limit); + +/** + * acpigen_write_pss_package() - Write a PSS package + * + * See ACPI v6.3 section 8.4.6: Processor Performance Control + * + * @ctx: ACPI context pointer + * @corefreq: CPU core frequency in MHz + * @translat: worst-case latency in uS that the CPU is unavailable during a + * transition from any performance state to this performance state + * @busmlat: worst-case latency in microseconds that Bus Masters are prevented + * from accessing memory during a transition from any performance state to + * this performance state + * @control: Value to write to PERF_CTRL to move to this performance state + * @status: Expected PERF_STATUS value when in this state + */ +void acpigen_write_pss_package(struct acpi_ctx *ctx, uint corefreq, uint power, + uint translat, uint busmlat, uint control, + uint status); + +/** + * acpigen_write_psd_package() - Write a PSD package + * + * Writes a P-State dependency package + * + * See ACPI v6.3 section 8.4.6.5: _PSD (P-State Dependency) + * + * @ctx: ACPI context pointer + * @domain: Dependency domain number to which this P state entry belongs + * @numprocs: Number of processors belonging to the domain for this logical + * processor’s P-states + * @coordtype: Coordination type + */ +void acpigen_write_psd_package(struct acpi_ctx *ctx, uint domain, uint numprocs, + enum psd_coord coordtype); + +/** + * acpigen_write_cst_package() - Write a _CST package + * + * See ACPI v6.3 section 8.4.2.1: _CST (C States) + * + * @ctx: ACPI context pointer + * @entry: Array of entries + * @nentries; Number of entries + */ +void acpigen_write_cst_package(struct acpi_ctx *ctx, + const struct acpi_cstate *entry, int nentries); + +/** + * acpigen_write_csd_package() - Write a _CSD Package + * + * See ACPI v6.3 section 8.4.2.2: _CSD (C-State Dependency) + * + * @ctx: ACPI context pointer + * @domain: dependency domain number to which this C state entry belongs + * @numprocs: number of processors belonging to the domain for the particular + * C-state + * @coordtype: Co-ordination type + * @index: Index of the C-State entry in the _CST object for which the + * dependency applies + */ +void acpigen_write_csd_package(struct acpi_ctx *ctx, uint domain, uint numprocs, + enum csd_coord coordtype, uint index); + +/** + * acpigen_write_tss_package() - Write a _TSS package + * + * @ctx: ACPI context pointer + * @entry: Entries to write + * @nentries: Number of entries to write + */ +void acpigen_write_tss_package(struct acpi_ctx *ctx, + struct acpi_tstate *entry, int nentries); + +/** + * acpigen_write_tsd_package() - Write a _TSD package + * + * See ACPI v6.3 section 8.4.5.4: _TSD (T-State Dependency) + * + * @ctx: ACPI context pointer + * @domain: dependency domain number to which this T state entry belongs + * @numprocs: Number of processors belonging to the domain for this logical + * processor’s T-states + * @coordtype: Coordination type + */ +void acpigen_write_tsd_package(struct acpi_ctx *ctx, uint domain, uint numprocs, + enum psd_coord coordtype); + #endif diff --git a/lib/acpi/acpigen.c b/lib/acpi/acpigen.c index b9985075cde..e395226e3de 100644 --- a/lib/acpi/acpigen.c +++ b/lib/acpi/acpigen.c @@ -481,6 +481,53 @@ void acpigen_write_register_resource(struct acpi_ctx *ctx, acpigen_write_resourcetemplate_footer(ctx); } +void acpigen_write_ppc(struct acpi_ctx *ctx, uint num_pstates) +{ + /* + * Method (_PPC, 0, NotSerialized) + * { + * Return (num_pstates) + * } + */ + acpigen_write_method(ctx, "_PPC", 0); + acpigen_emit_byte(ctx, RETURN_OP); + acpigen_write_byte(ctx, num_pstates); + acpigen_pop_len(ctx); +} + +/* + * Generates a func with max supported P-states saved + * in the variable PPCM. + */ +void acpigen_write_ppc_nvs(struct acpi_ctx *ctx) +{ + /* + * Method (_PPC, 0, NotSerialized) + * { + * Return (PPCM) + * } + */ + acpigen_write_method(ctx, "_PPC", 0); + acpigen_emit_byte(ctx, RETURN_OP); + acpigen_emit_namestring(ctx, "PPCM"); + acpigen_pop_len(ctx); +} + +void acpigen_write_tpc(struct acpi_ctx *ctx, const char *gnvs_tpc_limit) +{ + /* + * // Sample _TPC method + * Method (_TPC, 0, NotSerialized) + * { + * Return (\TLVL) + * } + */ + acpigen_write_method(ctx, "_TPC", 0); + acpigen_emit_byte(ctx, RETURN_OP); + acpigen_emit_namestring(ctx, gnvs_tpc_limit); + acpigen_pop_len(ctx); +} + void acpigen_write_prw(struct acpi_ctx *ctx, uint wake, uint level) { /* Name (_PRW, Package () { wake, level } */ @@ -491,6 +538,126 @@ void acpigen_write_prw(struct acpi_ctx *ctx, uint wake, uint level) acpigen_pop_len(ctx); } +void acpigen_write_pss_package(struct acpi_ctx *ctx, u32 core_freq, u32 power, + u32 trans_lat, u32 busm_lat, u32 control, + u32 status) +{ + acpigen_write_package(ctx, 6); + acpigen_write_dword(ctx, core_freq); + acpigen_write_dword(ctx, power); + acpigen_write_dword(ctx, trans_lat); + acpigen_write_dword(ctx, busm_lat); + acpigen_write_dword(ctx, control); + acpigen_write_dword(ctx, status); + acpigen_pop_len(ctx); + + log_debug("PSS: %uMHz power %u control 0x%x status 0x%x\n", + core_freq, power, control, status); +} + +void acpigen_write_psd_package(struct acpi_ctx *ctx, uint domain, uint numprocs, + enum psd_coord coordtype) +{ + acpigen_write_name(ctx, "_PSD"); + acpigen_write_package(ctx, 1); + acpigen_write_package(ctx, 5); + acpigen_write_byte(ctx, 5); // 5 values + acpigen_write_byte(ctx, 0); // revision 0 + acpigen_write_dword(ctx, domain); + acpigen_write_dword(ctx, coordtype); + acpigen_write_dword(ctx, numprocs); + acpigen_pop_len(ctx); + acpigen_pop_len(ctx); +} + +static void acpigen_write_cst_package_entry(struct acpi_ctx *ctx, + const struct acpi_cstate *cstate) +{ + acpigen_write_package(ctx, 4); + acpigen_write_register_resource(ctx, &cstate->resource); + acpigen_write_dword(ctx, cstate->ctype); + acpigen_write_dword(ctx, cstate->latency); + acpigen_write_dword(ctx, cstate->power); + acpigen_pop_len(ctx); +} + +void acpigen_write_cst_package(struct acpi_ctx *ctx, + const struct acpi_cstate *cstate, int nentries) +{ + int i; + + acpigen_write_name(ctx, "_CST"); + acpigen_write_package(ctx, nentries + 1); + acpigen_write_dword(ctx, nentries); + + for (i = 0; i < nentries; i++) + acpigen_write_cst_package_entry(ctx, cstate + i); + + acpigen_pop_len(ctx); +} + +void acpigen_write_csd_package(struct acpi_ctx *ctx, uint domain, uint numprocs, + enum csd_coord coordtype, uint index) +{ + acpigen_write_name(ctx, "_CSD"); + acpigen_write_package(ctx, 1); + acpigen_write_package(ctx, 6); + acpigen_write_byte(ctx, 6); // 6 values + acpigen_write_byte(ctx, 0); // revision 0 + acpigen_write_dword(ctx, domain); + acpigen_write_dword(ctx, coordtype); + acpigen_write_dword(ctx, numprocs); + acpigen_write_dword(ctx, index); + acpigen_pop_len(ctx); + acpigen_pop_len(ctx); +} + +void acpigen_write_tss_package(struct acpi_ctx *ctx, + struct acpi_tstate *entry, int nentries) +{ + /* + * Sample _TSS package with 100% and 50% duty cycles + * Name (_TSS, Package (0x02) + * { + * Package(){100, 1000, 0, 0x00, 0) + * Package(){50, 520, 0, 0x18, 0) + * }) + */ + struct acpi_tstate *tstate = entry; + int i; + + acpigen_write_name(ctx, "_TSS"); + acpigen_write_package(ctx, nentries); + + for (i = 0; i < nentries; i++) { + acpigen_write_package(ctx, 5); + acpigen_write_dword(ctx, tstate->percent); + acpigen_write_dword(ctx, tstate->power); + acpigen_write_dword(ctx, tstate->latency); + acpigen_write_dword(ctx, tstate->control); + acpigen_write_dword(ctx, tstate->status); + acpigen_pop_len(ctx); + tstate++; + } + + acpigen_pop_len(ctx); +} + +void acpigen_write_tsd_package(struct acpi_ctx *ctx, u32 domain, u32 numprocs, + enum psd_coord coordtype) +{ + acpigen_write_name(ctx, "_TSD"); + acpigen_write_package(ctx, 1); + acpigen_write_package(ctx, 5); + acpigen_write_byte(ctx, 5); // 5 values + acpigen_write_byte(ctx, 0); // revision 0 + acpigen_write_dword(ctx, domain); + acpigen_write_dword(ctx, coordtype); + acpigen_write_dword(ctx, numprocs); + acpigen_pop_len(ctx); + acpigen_pop_len(ctx); +} + /* * ToUUID(uuid) * diff --git a/test/dm/acpigen.c b/test/dm/acpigen.c index 4206f5ae3cf..b6d048a1c9a 100644 --- a/test/dm/acpigen.c +++ b/test/dm/acpigen.c @@ -1450,3 +1450,297 @@ static int dm_test_acpi_write_processor_cnot(struct unit_test_state *uts) return 0; } DM_TEST(dm_test_acpi_write_processor_cnot, 0); + +/* Test acpigen_write_tpc */ +static int dm_test_acpi_write_tpc(struct unit_test_state *uts) +{ + struct acpi_ctx *ctx; + u8 *ptr; + + ut_assertok(alloc_context(&ctx)); + + ptr = acpigen_get_current(ctx); + acpigen_write_tpc(ctx, "\\TLVL"); + + ut_asserteq(METHOD_OP, *ptr++); + ptr += 3; /* skip length */ + ut_asserteq_strn("_TPC", (char *)ptr); + ptr += 4; + ut_asserteq(0, *ptr++); + ut_asserteq(RETURN_OP, *ptr++); + ut_asserteq_strn("\\TLVL", (char *)ptr); + ptr += 5; + + ut_asserteq_ptr(ptr, ctx->current); + + free_context(&ctx); + + return 0; +} +DM_TEST(dm_test_acpi_write_tpc, 0); + +/* Test acpigen_write_pss_package(), etc. */ +static int dm_test_acpi_write_pss_psd(struct unit_test_state *uts) +{ + struct acpi_ctx *ctx; + u8 *ptr; + + ut_assertok(alloc_context(&ctx)); + + ptr = acpigen_get_current(ctx); + acpigen_write_pss_package(ctx, 1, 2, 3, 4, 5, 6); + ut_asserteq(PACKAGE_OP, *ptr++); + ptr += 3; /* skip length */ + ut_asserteq(6, *ptr++); + + ut_asserteq(DWORD_PREFIX, *ptr++); + ut_asserteq(1, get_unaligned((u32 *)ptr)); + ptr += 5; + + ut_asserteq(2, get_unaligned((u32 *)ptr)); + ptr += 5; + + ut_asserteq(3, get_unaligned((u32 *)ptr)); + ptr += 5; + + ut_asserteq(4, get_unaligned((u32 *)ptr)); + ptr += 5; + + ut_asserteq(5, get_unaligned((u32 *)ptr)); + ptr += 5; + + ut_asserteq(6, get_unaligned((u32 *)ptr)); + ptr += 4; + + acpigen_write_psd_package(ctx, 6, 7, HW_ALL); + ut_asserteq(NAME_OP, *ptr++); + ut_asserteq_strn("_PSD", (char *)ptr); + ptr += 4; + ut_asserteq(PACKAGE_OP, *ptr++); + ptr += 3; /* skip length */ + ut_asserteq(1, *ptr++); + ut_asserteq(PACKAGE_OP, *ptr++); + ptr += 3; /* skip length */ + ut_asserteq(5, *ptr++); + + ut_asserteq(BYTE_PREFIX, *ptr++); + ut_asserteq(5, *ptr++); + ut_asserteq(BYTE_PREFIX, *ptr++); + ut_asserteq(0, *ptr++); + + ut_asserteq(DWORD_PREFIX, *ptr++); + ut_asserteq(6, get_unaligned((u32 *)ptr)); + ptr += 5; + + ut_asserteq(HW_ALL, get_unaligned((u32 *)ptr)); + ptr += 5; + + ut_asserteq(7, get_unaligned((u32 *)ptr)); + ptr += 4; + + ut_asserteq_ptr(ptr, ctx->current); + + free_context(&ctx); + + return 0; +} +DM_TEST(dm_test_acpi_write_pss_psd, 0); + +/* Test acpi_write_cst_package() */ +static int dm_test_acpi_write_cst(struct unit_test_state *uts) +{ + static struct acpi_cstate cstate_map[] = { + { + /* C1 */ + .ctype = 1, /* ACPI C1 */ + .latency = 1, + .power = 1000, + .resource = { + .space_id = ACPI_ADDRESS_SPACE_FIXED, + }, + }, { + .ctype = 2, /* ACPI C2 */ + .latency = 50, + .power = 10, + .resource = { + .space_id = ACPI_ADDRESS_SPACE_IO, + .bit_width = 8, + .addrl = 0x415, + }, + }, + }; + int nentries = ARRAY_SIZE(cstate_map); + struct acpi_ctx *ctx; + u8 *ptr; + int i; + + ut_assertok(alloc_context(&ctx)); + + ptr = acpigen_get_current(ctx); + acpigen_write_cst_package(ctx, cstate_map, nentries); + + ut_asserteq(NAME_OP, *ptr++); + ut_asserteq_strn("_CST", (char *)ptr); + ptr += 4; + ut_asserteq(PACKAGE_OP, *ptr++); + ptr += 3; /* skip length */ + ut_asserteq(nentries + 1, *ptr++); + ut_asserteq(DWORD_PREFIX, *ptr++); + ut_asserteq(nentries, get_unaligned((u32 *)ptr)); + ptr += 4; + + for (i = 0; i < nentries; i++) { + ut_asserteq(PACKAGE_OP, *ptr++); + ptr += 3; /* skip length */ + ut_asserteq(4, *ptr++); + ut_asserteq(BUFFER_OP, *ptr++); + ptr += 0x17; + ut_asserteq(DWORD_PREFIX, *ptr++); + ut_asserteq(cstate_map[i].ctype, get_unaligned((u32 *)ptr)); + ptr += 5; + ut_asserteq(cstate_map[i].latency, get_unaligned((u32 *)ptr)); + ptr += 5; + ut_asserteq(cstate_map[i].power, get_unaligned((u32 *)ptr)); + ptr += 4; + } + + ut_asserteq_ptr(ptr, ctx->current); + + free_context(&ctx); + + return 0; +} +DM_TEST(dm_test_acpi_write_cst, 0); + +/* Test acpi_write_cst_package() */ +static int dm_test_acpi_write_csd(struct unit_test_state *uts) +{ + struct acpi_ctx *ctx; + u8 *ptr; + + ut_assertok(alloc_context(&ctx)); + + ptr = acpigen_get_current(ctx); + acpigen_write_csd_package(ctx, 12, 34, CSD_HW_ALL, 56); + + ut_asserteq(NAME_OP, *ptr++); + ut_asserteq_strn("_CSD", (char *)ptr); + ptr += 4; + ut_asserteq(PACKAGE_OP, *ptr++); + ptr += 3; /* skip length */ + ut_asserteq(1, *ptr++); + ut_asserteq(PACKAGE_OP, *ptr++); + ptr += 3; /* skip length */ + ut_asserteq(6, *ptr++); + + ut_asserteq(BYTE_PREFIX, *ptr++); + ut_asserteq(6, *ptr++); + ut_asserteq(BYTE_PREFIX, *ptr++); + ut_asserteq(0, *ptr++); + ut_asserteq(DWORD_PREFIX, *ptr++); + ut_asserteq(12, get_unaligned((u32 *)ptr)); + ptr += 5; + ut_asserteq(CSD_HW_ALL, get_unaligned((u32 *)ptr)); + ptr += 5; + ut_asserteq(34, get_unaligned((u32 *)ptr)); + ptr += 5; + ut_asserteq(56, get_unaligned((u32 *)ptr)); + ptr += 4; + + ut_asserteq_ptr(ptr, ctx->current); + + free_context(&ctx); + + return 0; +} +DM_TEST(dm_test_acpi_write_csd, 0); + +/* Test acpigen_write_tss_package() */ +static int dm_test_acpi_write_tss(struct unit_test_state *uts) +{ + static struct acpi_tstate tstate_list[] = { + { 1, 2, 3, 4, 5, }, + { 6, 7, 8, 9, 10, }, + }; + int nentries = ARRAY_SIZE(tstate_list); + struct acpi_ctx *ctx; + u8 *ptr; + int i; + + ut_assertok(alloc_context(&ctx)); + + ptr = acpigen_get_current(ctx); + acpigen_write_tss_package(ctx, tstate_list, nentries); + + ut_asserteq(NAME_OP, *ptr++); + ut_asserteq_strn("_TSS", (char *)ptr); + ptr += 4; + ut_asserteq(PACKAGE_OP, *ptr++); + ptr += 3; /* skip length */ + ut_asserteq(nentries, *ptr++); + + for (i = 0; i < nentries; i++) { + ut_asserteq(PACKAGE_OP, *ptr++); + ptr += 3; /* skip length */ + ut_asserteq(5, *ptr++); + ut_asserteq(DWORD_PREFIX, *ptr++); + ut_asserteq(tstate_list[i].percent, get_unaligned((u32 *)ptr)); + ptr += 5; + ut_asserteq(tstate_list[i].power, get_unaligned((u32 *)ptr)); + ptr += 5; + ut_asserteq(tstate_list[i].latency, get_unaligned((u32 *)ptr)); + ptr += 5; + ut_asserteq(tstate_list[i].control, get_unaligned((u32 *)ptr)); + ptr += 5; + ut_asserteq(tstate_list[i].status, get_unaligned((u32 *)ptr)); + ptr += 4; + } + + ut_asserteq_ptr(ptr, ctx->current); + + free_context(&ctx); + + return 0; +} +DM_TEST(dm_test_acpi_write_tss, 0); + +/* Test acpigen_write_tsd_package() */ +static int dm_test_acpi_write_tsd_package(struct unit_test_state *uts) +{ + struct acpi_ctx *ctx; + u8 *ptr; + + ut_assertok(alloc_context(&ctx)); + + ptr = acpigen_get_current(ctx); + acpigen_write_tsd_package(ctx, 12, 34, HW_ALL); + + ut_asserteq(NAME_OP, *ptr++); + ut_asserteq_strn("_TSD", (char *)ptr); + ptr += 4; + ut_asserteq(PACKAGE_OP, *ptr++); + ptr += 3; /* skip length */ + ut_asserteq(1, *ptr++); + ut_asserteq(PACKAGE_OP, *ptr++); + ptr += 3; /* skip length */ + ut_asserteq(5, *ptr++); + + ut_asserteq(BYTE_PREFIX, *ptr++); + ut_asserteq(5, *ptr++); + ut_asserteq(BYTE_PREFIX, *ptr++); + ut_asserteq(0, *ptr++); + ut_asserteq(DWORD_PREFIX, *ptr++); + ut_asserteq(12, get_unaligned((u32 *)ptr)); + ptr += 5; + ut_asserteq(CSD_HW_ALL, get_unaligned((u32 *)ptr)); + ptr += 5; + ut_asserteq(34, get_unaligned((u32 *)ptr)); + ptr += 4; + + ut_asserteq_ptr(ptr, ctx->current); + + free_context(&ctx); + + return 0; +} +DM_TEST(dm_test_acpi_write_tsd_package, 0);