From patchwork Wed Sep 9 16:44:05 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Etienne Carriere X-Patchwork-Id: 249515 Delivered-To: patch@linaro.org Received: by 2002:a05:6e02:dcd:0:0:0:0 with SMTP id l13csp542742ilj; Wed, 9 Sep 2020 09:45:35 -0700 (PDT) X-Google-Smtp-Source: ABdhPJwCMd1tlYqHaZiQgAxa384gAe9mvuo/OPJMzeAADJOC4KtL1xDmJUxc7G0Jd3gXB87AtIm0 X-Received: by 2002:a17:906:72d2:: with SMTP id m18mr4446055ejl.220.1599669935767; Wed, 09 Sep 2020 09:45:35 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1599669935; cv=none; d=google.com; s=arc-20160816; b=D952sXBToRFziv16NTeDzScjsNHRcxIzZaeiOvXVSMaBCjYITE5laVgLgzWfu9hDpv +SvaILVwQxG9V9kcrKRcuT05yqJlEYUrtJlbHo5oG6mTtvy3snmpUZldGqgSWPx8sYm3 5W3IkplCVLMrxw6GKTh0h9WwEQKfJntle22Vhqat0edl1PmDHQNBYtKHh39HalM5F1Qj kGWYQCKXI7iKhzQkb5Q02c0q58NyMbc8ihLt/feiPg/a5UNm97sFbIo06HZPgUntpLmR FC0W3Tv2gSUOoUIh9elR+oJ2I2F7sVljk26K9Htxs9xIxADByQNTliiSCvAzhxyeyIUH QSKg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:references:in-reply-to :message-id:date:subject:cc:to:from:dkim-signature; bh=hf9bvnO2AOEa5TUqBNhednbomgYVXY76JjFO2ZXkHJE=; b=DzIQISPmpLF4Oky5jq+WukRfypt8jpc43id0/g1bwfsHUZqWPb+npEiKmmXUpC3YKS Vd07p/D72pB27BP53DSjYbbc5fwYQ8ROrUBdufJXcTDZE84ITEOlwB9tc9ObZnmPhUB7 AvQshLautD5iCGnLFkw5sXV1n2k8Bs8Xsl9dQraeREa/sFtQZRK3szqj9NU9JqkSAJUo +3f/mcdB5MB2LK8uVRrOnFKrMWJ360KO2r20Lc93NnWXcJ7YASf6KN5eMHsudlqe1Qfg gB2GHMDSGVGJGzqriQVTsi7zvc/AjfpkL5yz/PLfWuTy08ZnTgtP9x/fyY9QR3Y4BRVZ 0IKw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b="TT1n8/DH"; spf=pass (google.com: domain of u-boot-bounces@lists.denx.de designates 2a01:238:438b:c500:173d:9f52:ddab:ee01 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from phobos.denx.de (phobos.denx.de. [2a01:238:438b:c500:173d:9f52:ddab:ee01]) by mx.google.com with ESMTPS id h24si1847986edv.391.2020.09.09.09.45.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 09 Sep 2020 09:45:35 -0700 (PDT) Received-SPF: pass (google.com: domain of u-boot-bounces@lists.denx.de designates 2a01:238:438b:c500:173d:9f52:ddab:ee01 as permitted sender) client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b="TT1n8/DH"; spf=pass (google.com: domain of u-boot-bounces@lists.denx.de designates 2a01:238:438b:c500:173d:9f52:ddab:ee01 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 075CC822EC; Wed, 9 Sep 2020 18:44:29 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="TT1n8/DH"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 20B8A822E1; Wed, 9 Sep 2020 18:44:25 +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,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,SPF_HELO_NONE,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-wr1-x441.google.com (mail-wr1-x441.google.com [IPv6:2a00:1450:4864:20::441]) (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 A83CE81B79 for ; Wed, 9 Sep 2020 18:44:20 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=etienne.carriere@linaro.org Received: by mail-wr1-x441.google.com with SMTP id w5so3681094wrp.8 for ; Wed, 09 Sep 2020 09:44:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=hf9bvnO2AOEa5TUqBNhednbomgYVXY76JjFO2ZXkHJE=; b=TT1n8/DH14q7m4FiO+02cWfZhrCMI9k/B8LV5uHUXmJLfYOxsc8d+Lgc/0zZqUbqUF UFrNAHRnrX+u8pz4i5R/1r1UqK4iir7nA19UWgGjhvRnwpliab3a1+NJCvrBwX6QeLif dt9QFgNKHHorNpLS+a8dZmG4NZCf5A9QYI+C0wA3vFBL3wBJny75nA4tfsCCSvXxKu9B 89+brW++a6QYbRRZv2tPxtKWiT9W3DAVHuxm39eeWn8dd0lv5j0cjxviRgZTX0N+SB98 kZ2haJcuRp//L7G+th/UPJ1rkHJCgD9gyB9itwAz4v545/NQQtWcgtTLYzFH0/krFKLz 036g== 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; bh=hf9bvnO2AOEa5TUqBNhednbomgYVXY76JjFO2ZXkHJE=; b=NBa6CTeY/3iVceACDYnjE+7Go5zuSVJVxskQHx25NyvmFPnW5jX4KNw+wfuYD6PdYs 8rmryurNTUGNKd+Lwy8Lji4MqKFwQg0KgznjJVZ5aBEmPYhxzUjux/9qnVel7Ww2DmYp 2FsHxRwWHvae4Ppz49SswTeIcowhmi7jw61UOXBoAwjxvcwAt7RW5O4gEm+v2A9FO4FB jmSYPPGDjyd5RmGNs/70udUs9dgQiV4pOwYyJl6caVUq5gbkJqyTOjpFN3wDeQH4zifI vaokFwlF5caDc7wXSsp3tzT0TIiHYfxa4zZSgDy4mUuOFoa1yCFy8q4c5UCHRnTUjXsA jgWw== X-Gm-Message-State: AOAM533PPd/KBdTOpHegnAUih9eB4H3s4oM3bzvZqCu0mc5UjztGliwG phVZpaBdSGE6QixRdDVX39dRxi0Oi6qs0A0XvYk= X-Received: by 2002:adf:fd8d:: with SMTP id d13mr5052085wrr.104.1599669859969; Wed, 09 Sep 2020 09:44:19 -0700 (PDT) Received: from lmecxl0524.lme.st.com ([2a04:cec0:100d:d03f:c9d0:c7b0:9925:5cde]) by smtp.gmail.com with ESMTPSA id t15sm4468301wmj.15.2020.09.09.09.44.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 09 Sep 2020 09:44:19 -0700 (PDT) From: Etienne Carriere To: u-boot@lists.denx.de Cc: Simon Glass , Lukasz Majewski , Peng Fan , Sudeep Holla , Etienne Carriere Subject: [PATCH v4 6/8] firmware: scmi: sandbox test for SCMI clocks Date: Wed, 9 Sep 2020 18:44:05 +0200 Message-Id: <20200909164407.14327-6-etienne.carriere@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200909164407.14327-1-etienne.carriere@linaro.org> References: <20200909164407.14327-1-etienne.carriere@linaro.org> 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 Add tests for SCMI clocks. A test device driver sandbox-scmi_devices.c is used to get clock resources, allowing further clock manipulation. Change sandbox-smci_agent to emulate 3 clocks exposed through 2 agents. Add DM test scmi_clocks to test these 3 clocks. Update DM test sandbox_scmi_agent with load/remove test sequences factorized by {load|remove}_sandbox_scmi_test_devices() helper functions. Signed-off-by: Etienne Carriere Cc: Simon Glass Cc: Peng Fan Cc: Sudeep Holla --- Changes in v4: - Move SCMI test devices instances from BSS to test device private data and update test/dm/scmi.c accordingly. - Update sandbox_scmi_devices_ctx() helper to add device reference arg. - Fix spelling issues in inline comments. - Rename local variables rc to ret for consistency. Changes in v3: - New commit in the series, addresses review comments on test support. ut_dm_scmi_clocks test SCMI are found and behave as expected for the implemented clk uclass methods. --- arch/sandbox/dts/test.dts | 15 ++ arch/sandbox/include/asm/scmi_test.h | 39 +++++ configs/sandbox_defconfig | 1 + drivers/firmware/scmi/Makefile | 2 +- drivers/firmware/scmi/sandbox-scmi_agent.c | 169 ++++++++++++++++++- drivers/firmware/scmi/sandbox-scmi_devices.c | 75 ++++++++ test/dm/scmi.c | 141 +++++++++++++++- 7 files changed, 431 insertions(+), 11 deletions(-) create mode 100644 drivers/firmware/scmi/sandbox-scmi_devices.c -- 2.17.1 Reviewed-by: Simon Glass diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index dd3b43885e..61acd8d79f 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -361,6 +361,11 @@ compatible = "sandbox,scmi-agent"; #address-cells = <1>; #size-cells = <0>; + + clk_scmi0: protocol@14 { + reg = <0x14>; + #clock-cells = <1>; + }; }; sandbox-scmi-agent@1 { @@ -368,6 +373,11 @@ #address-cells = <1>; #size-cells = <0>; + clk_scmi1: protocol@14 { + reg = <0x14>; + #clock-cells = <1>; + }; + protocol@10 { reg = <0x10>; }; @@ -1052,6 +1062,11 @@ compatible = "sandbox,virtio2"; }; + sandbox_scmi { + compatible = "sandbox,scmi-devices"; + clocks = <&clk_scmi0 7>, <&clk_scmi0 3>, <&clk_scmi1 1>; + }; + pinctrl { compatible = "sandbox,pinctrl"; diff --git a/arch/sandbox/include/asm/scmi_test.h b/arch/sandbox/include/asm/scmi_test.h index a811fe19c3..63093fdb4d 100644 --- a/arch/sandbox/include/asm/scmi_test.h +++ b/arch/sandbox/include/asm/scmi_test.h @@ -10,12 +10,28 @@ struct udevice; struct sandbox_scmi_agent; struct sandbox_scmi_service; +/** + * struct sandbox_scmi_clk - Simulated clock exposed by SCMI + * @id: Identifier of the clock used in the SCMI protocol + * @enabled: Clock state: true if enabled, false if disabled + * @rate: Clock rate in Hertz + */ +struct sandbox_scmi_clk { + uint id; + bool enabled; + ulong rate; +}; + /** * struct sandbox_scmi_agent - Simulated SCMI service seen by SCMI agent * @idx: Identifier for the SCMI agent, its index + * @clk: Simulated clocks + * @clk_count: Simulated clocks array size */ struct sandbox_scmi_agent { uint idx; + struct sandbox_scmi_clk *clk; + size_t clk_count; }; /** @@ -28,16 +44,39 @@ struct sandbox_scmi_service { size_t agent_count; }; +/** + * struct sandbox_scmi_devices - Reference to devices probed through SCMI + * @clk: Array the clock devices + * @clk_count: Number of clock devices probed + */ +struct sandbox_scmi_devices { + struct clk *clk; + size_t clk_count; +}; + #ifdef CONFIG_SCMI_FIRMWARE /** * sandbox_scmi_service_context - Get the simulated SCMI services context * @return: Reference to backend simulated resources state */ struct sandbox_scmi_service *sandbox_scmi_service_ctx(void); + +/** + * sandbox_scmi_devices_get_ref - Get references to devices accessed through SCMI + * @dev: Reference to the test device used get test resources + * @return: Reference to the devices probed by the SCMI test + */ +struct sandbox_scmi_devices *sandbox_scmi_devices_ctx(struct udevice *dev); #else static inline struct sandbox_scmi_service *sandbox_scmi_service_ctx(void) { return NULL; } + +static inline +struct sandbox_scmi_devices *sandbox_scmi_devices_ctx(struct udevice *dev) +{ + return NULL; +} #endif /* CONFIG_SCMI_FIRMWARE */ #endif /* __SANDBOX_SCMI_TEST_H */ diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index 2c130c01f0..7d71c805dc 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -122,6 +122,7 @@ CONFIG_BUTTON=y CONFIG_BUTTON_GPIO=y CONFIG_CLK=y CONFIG_CLK_COMPOSITE_CCF=y +CONFIG_CLK_SCMI=y CONFIG_SANDBOX_CLK_CCF=y CONFIG_CPU=y CONFIG_DM_DEMO=y diff --git a/drivers/firmware/scmi/Makefile b/drivers/firmware/scmi/Makefile index 2f782bbd55..e1e0224066 100644 --- a/drivers/firmware/scmi/Makefile +++ b/drivers/firmware/scmi/Makefile @@ -2,4 +2,4 @@ obj-y += scmi_agent-uclass.o obj-y += smt.o obj-$(CONFIG_ARM_SMCCC) += smccc_agent.o obj-$(CONFIG_DM_MAILBOX) += mailbox_agent.o -obj-$(CONFIG_SANDBOX) += sandbox-scmi_agent.o +obj-$(CONFIG_SANDBOX) += sandbox-scmi_agent.o sandbox-scmi_devices.o diff --git a/drivers/firmware/scmi/sandbox-scmi_agent.c b/drivers/firmware/scmi/sandbox-scmi_agent.c index 3179438aab..ff590988a6 100644 --- a/drivers/firmware/scmi/sandbox-scmi_agent.c +++ b/drivers/firmware/scmi/sandbox-scmi_agent.c @@ -16,18 +16,34 @@ /* * The sandbox SCMI agent driver simulates to some extend a SCMI message * processing. It simulates few of the SCMI services for some of the - * SCMI protocols embedded in U-Boot. Currently none. + * SCMI protocols embedded in U-Boot. Currently: + * - SCMI clock protocol: emulate 2 agents each exposing few clocks * - * This driver simulates 2 SCMI agents for test purpose. + * Agent #0 simulates 2 clocks. + * See IDs in scmi0_clk[] and "sandbox-scmi-agent@0" in test.dts. + * + * Agent #1 simulates 1 clock. + * See IDs in scmi1_clk[] and "sandbox-scmi-agent@1" in test.dts. + * + * All clocks are default disabled. * * This Driver exports sandbox_scmi_service_ct() for the test sequence to * get the state of the simulated services (clock state, rate, ...) and * check back-end device state reflects the request send through the - * various uclass devices, currently nothing. + * various uclass devices, currently only clock controllers. */ #define SANDBOX_SCMI_AGENT_COUNT 2 +static struct sandbox_scmi_clk scmi0_clk[] = { + { .id = 7, .rate = 1000 }, + { .id = 3, .rate = 333 }, +}; + +static struct sandbox_scmi_clk scmi1_clk[] = { + { .id = 1, .rate = 44 }, +}; + /* The list saves to simulted end devices references for test purpose */ struct sandbox_scmi_agent *sandbox_scmi_agent_list[SANDBOX_SCMI_AGENT_COUNT]; @@ -46,17 +62,158 @@ static void debug_print_agent_state(struct udevice *dev, char *str) struct sandbox_scmi_agent *agent = dev_get_priv(dev); dev_dbg(dev, "Dump sandbox_scmi_agent %u: %s\n", agent->idx, str); + dev_dbg(dev, " scmi%u_clk (%zu): %d/%ld, %d/%ld, %d/%ld, ...\n", + agent->idx, + agent->clk_count, + agent->clk_count ? agent->clk[0].enabled : -1, + agent->clk_count ? agent->clk[0].rate : -1, + agent->clk_count > 1 ? agent->clk[1].enabled : -1, + agent->clk_count > 1 ? agent->clk[1].rate : -1, + agent->clk_count > 2 ? agent->clk[2].enabled : -1, + agent->clk_count > 2 ? agent->clk[2].rate : -1); }; +static struct sandbox_scmi_clk *get_scmi_clk_state(uint agent_id, uint clock_id) +{ + struct sandbox_scmi_clk *target = NULL; + size_t target_count = 0; + size_t n; + + switch (agent_id) { + case 0: + target = scmi0_clk; + target_count = ARRAY_SIZE(scmi0_clk); + break; + case 1: + target = scmi1_clk; + target_count = ARRAY_SIZE(scmi1_clk); + break; + default: + return NULL; + } + + for (n = 0; n < target_count; n++) + if (target[n].id == clock_id) + return target + n; + + return NULL; +} + +/* + * Sandbox SCMI agent ops + */ + +static int sandbox_scmi_clock_rate_set(struct udevice *dev, + struct scmi_msg *msg) +{ + struct sandbox_scmi_agent *agent = dev_get_priv(dev); + struct scmi_clk_rate_set_in *in = NULL; + struct scmi_clk_rate_set_out *out = NULL; + struct sandbox_scmi_clk *clk_state = NULL; + + if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) || + !msg->out_msg || msg->out_msg_sz < sizeof(*out)) + return -EINVAL; + + in = (struct scmi_clk_rate_set_in *)msg->in_msg; + out = (struct scmi_clk_rate_set_out *)msg->out_msg; + + clk_state = get_scmi_clk_state(agent->idx, in->clock_id); + if (!clk_state) { + dev_err(dev, "Unexpected clock ID %u\n", in->clock_id); + + out->status = SCMI_NOT_FOUND; + } else { + u64 rate = ((u64)in->rate_msb << 32) + in->rate_lsb; + + clk_state->rate = (ulong)rate; + + out->status = SCMI_SUCCESS; + } + + return 0; +} + +static int sandbox_scmi_clock_rate_get(struct udevice *dev, + struct scmi_msg *msg) +{ + struct sandbox_scmi_agent *agent = dev_get_priv(dev); + struct scmi_clk_rate_get_in *in = NULL; + struct scmi_clk_rate_get_out *out = NULL; + struct sandbox_scmi_clk *clk_state = NULL; + + if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) || + !msg->out_msg || msg->out_msg_sz < sizeof(*out)) + return -EINVAL; + + in = (struct scmi_clk_rate_get_in *)msg->in_msg; + out = (struct scmi_clk_rate_get_out *)msg->out_msg; + + clk_state = get_scmi_clk_state(agent->idx, in->clock_id); + if (!clk_state) { + dev_err(dev, "Unexpected clock ID %u\n", in->clock_id); + + out->status = SCMI_NOT_FOUND; + } else { + out->rate_msb = (u32)((u64)clk_state->rate >> 32); + out->rate_lsb = (u32)clk_state->rate; + + out->status = SCMI_SUCCESS; + } + + return 0; +} + +static int sandbox_scmi_clock_gate(struct udevice *dev, struct scmi_msg *msg) +{ + struct sandbox_scmi_agent *agent = dev_get_priv(dev); + struct scmi_clk_state_in *in = NULL; + struct scmi_clk_state_out *out = NULL; + struct sandbox_scmi_clk *clk_state = NULL; + + if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) || + !msg->out_msg || msg->out_msg_sz < sizeof(*out)) + return -EINVAL; + + in = (struct scmi_clk_state_in *)msg->in_msg; + out = (struct scmi_clk_state_out *)msg->out_msg; + + clk_state = get_scmi_clk_state(agent->idx, in->clock_id); + if (!clk_state) { + dev_err(dev, "Unexpected clock ID %u\n", in->clock_id); + + out->status = SCMI_NOT_FOUND; + } else if (in->attributes > 1) { + out->status = SCMI_PROTOCOL_ERROR; + } else { + clk_state->enabled = in->attributes; + + out->status = SCMI_SUCCESS; + } + + return 0; +} + static int sandbox_scmi_test_process_msg(struct udevice *dev, struct scmi_msg *msg) { switch (msg->protocol_id) { + case SCMI_PROTOCOL_ID_CLOCK: + switch (msg->message_id) { + case SCMI_CLOCK_RATE_SET: + return sandbox_scmi_clock_rate_set(dev, msg); + case SCMI_CLOCK_RATE_GET: + return sandbox_scmi_clock_rate_get(dev, msg); + case SCMI_CLOCK_CONFIG_SET: + return sandbox_scmi_clock_gate(dev, msg); + default: + break; + } + break; case SCMI_PROTOCOL_ID_BASE: case SCMI_PROTOCOL_ID_POWER_DOMAIN: case SCMI_PROTOCOL_ID_SYSTEM: case SCMI_PROTOCOL_ID_PERF: - case SCMI_PROTOCOL_ID_CLOCK: case SCMI_PROTOCOL_ID_SENSOR: case SCMI_PROTOCOL_ID_RESET_DOMAIN: *(u32 *)msg->out_msg = SCMI_NOT_SUPPORTED; @@ -101,11 +258,15 @@ static int sandbox_scmi_test_probe(struct udevice *dev) case '0': *agent = (struct sandbox_scmi_agent){ .idx = 0, + .clk = scmi0_clk, + .clk_count = ARRAY_SIZE(scmi0_clk), }; break; case '1': *agent = (struct sandbox_scmi_agent){ .idx = 1, + .clk = scmi1_clk, + .clk_count = ARRAY_SIZE(scmi1_clk), }; break; default: diff --git a/drivers/firmware/scmi/sandbox-scmi_devices.c b/drivers/firmware/scmi/sandbox-scmi_devices.c new file mode 100644 index 0000000000..b3e411c5ac --- /dev/null +++ b/drivers/firmware/scmi/sandbox-scmi_devices.c @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2020, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include + +/* + * Simulate to some extent a SCMI exchange. + * This drivers gets SCMI resources and offers API function to the + * SCMI test sequence manipulate the resources, currently clocks. + */ + +#define SCMI_TEST_DEVICES_CLK_COUNT 3 + +/* + * struct sandbox_scmi_device_priv - Storage for device handles used by test + * @clk: Array of clock instances used by tests + * @devices: Resources exposed by sandbox_scmi_devices_ctx() + */ +struct sandbox_scmi_device_priv { + struct clk clk[SCMI_TEST_DEVICES_CLK_COUNT]; + struct sandbox_scmi_devices devices; +}; + +struct sandbox_scmi_devices *sandbox_scmi_devices_ctx(struct udevice *dev) +{ + struct sandbox_scmi_device_priv *priv = dev_get_priv(dev); + + if (priv) + return &priv->devices; + + return NULL; +} + +static int sandbox_scmi_devices_probe(struct udevice *dev) +{ + struct sandbox_scmi_device_priv *priv = dev_get_priv(dev); + int ret; + size_t n; + + priv->devices = (struct sandbox_scmi_devices){ + .clk = priv->clk, + .clk_count = SCMI_TEST_DEVICES_CLK_COUNT, + }; + + for (n = 0; n < SCMI_TEST_DEVICES_CLK_COUNT; n++) { + ret = clk_get_by_index(dev, n, priv->devices.clk + n); + if (ret) { + dev_err(dev, "%s: Failed on clk %zu\n", __func__, n); + return ret; + } + } + + return 0; +} + +static const struct udevice_id sandbox_scmi_devices_ids[] = { + { .compatible = "sandbox,scmi-devices" }, + { } +}; + +U_BOOT_DRIVER(sandbox_scmi_devices) = { + .name = "sandbox-scmi_devices", + .id = UCLASS_MISC, + .of_match = sandbox_scmi_devices_ids, + .priv_auto_alloc_size = sizeof(struct sandbox_scmi_device_priv), + .probe = sandbox_scmi_devices_probe, +}; diff --git a/test/dm/scmi.c b/test/dm/scmi.c index d8c1e71f12..aa46f31a47 100644 --- a/test/dm/scmi.c +++ b/test/dm/scmi.c @@ -13,26 +13,155 @@ */ #include +#include #include #include #include #include +#include #include +static int ut_assert_scmi_state_preprobe(struct unit_test_state *uts) +{ + struct sandbox_scmi_service *scmi_ctx = sandbox_scmi_service_ctx(); + + ut_assertnonnull(scmi_ctx); + if (scmi_ctx->agent_count) + ut_asserteq(2, scmi_ctx->agent_count); + + return 0; +} + +static int ut_assert_scmi_state_postprobe(struct unit_test_state *uts, + struct udevice *dev) +{ + struct sandbox_scmi_devices *scmi_devices; + struct sandbox_scmi_service *scmi_ctx; + + /* Device references to check context against test sequence */ + scmi_devices = sandbox_scmi_devices_ctx(dev); + + ut_assertnonnull(scmi_devices); + if (IS_ENABLED(CONFIG_CLK_SCMI)) + ut_asserteq(3, scmi_devices->clk_count); + + /* State of the simulated SCMI server exposed */ + scmi_ctx = sandbox_scmi_service_ctx(); + + ut_asserteq(2, scmi_ctx->agent_count); + + ut_assertnonnull(scmi_ctx->agent[0]); + ut_asserteq(2, scmi_ctx->agent[0]->clk_count); + ut_assertnonnull(scmi_ctx->agent[0]->clk); + + ut_assertnonnull(scmi_ctx->agent[1]); + ut_assertnonnull(scmi_ctx->agent[1]->clk); + ut_asserteq(1, scmi_ctx->agent[1]->clk_count); + + return 0; +} + +static int load_sandbox_scmi_test_devices(struct unit_test_state *uts, + struct udevice **dev) +{ + int ret; + + ret = ut_assert_scmi_state_preprobe(uts); + if (ret) + return ret; + + ut_assertok(uclass_get_device_by_name(UCLASS_MISC, "sandbox_scmi", + dev)); + ut_assertnonnull(*dev); + + return ut_assert_scmi_state_postprobe(uts, *dev); +} + +static int release_sandbox_scmi_test_devices(struct unit_test_state *uts, + struct udevice *dev) +{ + ut_assertok(device_remove(dev, DM_REMOVE_NORMAL)); + + /* Not sure test devices are fully removed, agent may not be visible */ + return 0; +} + /* * Test SCMI states when loading and releasing resources * related to SCMI drivers. */ static int dm_test_scmi_sandbox_agent(struct unit_test_state *uts) { - struct sandbox_scmi_service *scmi_ctx = sandbox_scmi_service_ctx(); + struct udevice *dev = NULL; + int ret; - ut_assertnonnull(scmi_ctx); - ut_asserteq(2, scmi_ctx->agent_count); - ut_assertnull(scmi_ctx->agent[0]); - ut_assertnull(scmi_ctx->agent[1]); + ret = load_sandbox_scmi_test_devices(uts, &dev); + if (!ret) + ret = release_sandbox_scmi_test_devices(uts, dev); - return 0; + return ret; } DM_TEST(dm_test_scmi_sandbox_agent, UT_TESTF_SCAN_FDT); + +static int dm_test_scmi_clocks(struct unit_test_state *uts) +{ + struct sandbox_scmi_devices *scmi_devices; + struct sandbox_scmi_service *scmi_ctx; + struct udevice *dev = NULL; + int ret_dev; + int ret; + + if (!IS_ENABLED(CONFIG_CLK_SCMI)) + return 0; + + ret = load_sandbox_scmi_test_devices(uts, &dev); + if (ret) + return ret; + + scmi_devices = sandbox_scmi_devices_ctx(dev); + scmi_ctx = sandbox_scmi_service_ctx(); + + /* Test SCMI clocks rate manipulation */ + ut_asserteq(1000, clk_get_rate(&scmi_devices->clk[0])); + ut_asserteq(333, clk_get_rate(&scmi_devices->clk[1])); + ut_asserteq(44, clk_get_rate(&scmi_devices->clk[2])); + + ret_dev = clk_set_rate(&scmi_devices->clk[1], 1088); + ut_assert(!ret_dev || ret_dev == 1088); + + ut_asserteq(1000, scmi_ctx->agent[0]->clk[0].rate); + ut_asserteq(1088, scmi_ctx->agent[0]->clk[1].rate); + ut_asserteq(44, scmi_ctx->agent[1]->clk[0].rate); + + ut_asserteq(1000, clk_get_rate(&scmi_devices->clk[0])); + ut_asserteq(1088, clk_get_rate(&scmi_devices->clk[1])); + ut_asserteq(44, clk_get_rate(&scmi_devices->clk[2])); + + /* restore original rate for further tests */ + ret_dev = clk_set_rate(&scmi_devices->clk[1], 333); + ut_assert(!ret_dev || ret_dev == 333); + + /* Test SCMI clocks gating manipulation */ + ut_assert(!scmi_ctx->agent[0]->clk[0].enabled); + ut_assert(!scmi_ctx->agent[0]->clk[1].enabled); + ut_assert(!scmi_ctx->agent[1]->clk[0].enabled); + + ut_asserteq(0, clk_enable(&scmi_devices->clk[1])); + ut_asserteq(0, clk_enable(&scmi_devices->clk[2])); + + ut_assert(!scmi_ctx->agent[0]->clk[0].enabled); + ut_assert(scmi_ctx->agent[0]->clk[1].enabled); + ut_assert(scmi_ctx->agent[1]->clk[0].enabled); + + ut_assertok(clk_disable(&scmi_devices->clk[1])); + ut_assertok(clk_disable(&scmi_devices->clk[2])); + + ut_assert(!scmi_ctx->agent[0]->clk[0].enabled); + ut_assert(!scmi_ctx->agent[0]->clk[1].enabled); + ut_assert(!scmi_ctx->agent[1]->clk[0].enabled); + + return release_sandbox_scmi_test_devices(uts, dev); +} + +DM_TEST(dm_test_scmi_clocks, UT_TESTF_SCAN_FDT);