Message ID | 20210219133341.3097-2-etienne.carriere@linaro.org |
---|---|
State | Superseded |
Headers | show |
Series | [v2,1/3] firmware: scmi: voltage regulator | expand |
On Fri, 19 Feb 2021 at 06:34, Etienne Carriere <etienne.carriere@linaro.org> wrote: > > Implement sandbox regulator devices for SCMI voltage domains > and test them in DM scmi tests. > > Signed-off-by: Etienne Carriere <etienne.carriere@linaro.org> > --- > Changes in v2: > - don't test IS_ENABLED(CONFIG_DM_REGULATOR_SCMI) in test/dm/scmi.c, > it's expected enabled when CONFIG_FIRMWARE_SCMI is enabled in sandbox. > --- > arch/sandbox/dts/test.dts | 23 +++ > arch/sandbox/include/asm/scmi_test.h | 20 ++ > configs/sandbox_defconfig | 1 + > drivers/firmware/scmi/sandbox-scmi_agent.c | 203 ++++++++++++++++++- > drivers/firmware/scmi/sandbox-scmi_devices.c | 25 ++- > test/dm/scmi.c | 58 ++++++ > 6 files changed, 327 insertions(+), 3 deletions(-) Reviewed-by: Simon Glass <sjg@chromium.org> thought below [..] > diff --git a/test/dm/scmi.c b/test/dm/scmi.c > index be60b44b3..792410338 100644 > --- a/test/dm/scmi.c > +++ b/test/dm/scmi.c > @@ -20,6 +20,7 @@ > #include <dm/device-internal.h> > #include <dm/test.h> > #include <linux/kconfig.h> > +#include <power/regulator.h> > #include <test/ut.h> > > static int ut_assert_scmi_state_preprobe(struct unit_test_state *uts) > @@ -47,6 +48,7 @@ static int ut_assert_scmi_state_postprobe(struct unit_test_state *uts, > ut_asserteq(3, scmi_devices->clk_count); > if (IS_ENABLED(CONFIG_RESET_SCMI)) > ut_asserteq(1, scmi_devices->reset_count); > + ut_asserteq(2, scmi_devices->regul_count); > > /* State of the simulated SCMI server exposed */ > scmi_ctx = sandbox_scmi_service_ctx(); > @@ -58,6 +60,8 @@ static int ut_assert_scmi_state_postprobe(struct unit_test_state *uts, > ut_assertnonnull(scmi_ctx->agent[0]->clk); > ut_asserteq(1, scmi_ctx->agent[0]->reset_count); > ut_assertnonnull(scmi_ctx->agent[0]->reset); > + ut_asserteq(2, scmi_ctx->agent[0]->voltd_count); > + ut_assertnonnull(scmi_ctx->agent[0]->voltd); > > ut_assertnonnull(scmi_ctx->agent[1]); > ut_assertnonnull(scmi_ctx->agent[1]->clk); > @@ -201,3 +205,57 @@ static int dm_test_scmi_resets(struct unit_test_state *uts) > } > > DM_TEST(dm_test_scmi_resets, UT_TESTF_SCAN_FDT); > + > +static int dm_test_scmi_voltage_domains(struct unit_test_state *uts) > +{ > + struct sandbox_scmi_devices *scmi_devices; > + struct sandbox_scmi_service *scmi_ctx; > + struct sandbox_scmi_voltd *sandbox_voltd; > + struct dm_regulator_uclass_plat *uc_pdata; > + struct udevice *dev; > + struct udevice *regul_dev; > + > + ut_assertok(load_sandbox_scmi_test_devices(uts, &dev)); > + > + scmi_devices = sandbox_scmi_devices_ctx(dev); > + scmi_ctx = sandbox_scmi_service_ctx(); > + > + /* Set/Get an SCMI voltage domain level */ > + sandbox_voltd = &scmi_ctx->agent[0]->voltd[0]; > + regul_dev = scmi_devices->regul[0]; > + ut_assert(regul_dev); > + > + uc_pdata = dev_get_uclass_plat(regul_dev); > + ut_assert(uc_pdata); > + > + ut_assertok(regulator_set_value(regul_dev, uc_pdata->min_uV)); > + ut_asserteq(sandbox_voltd->voltage_uv, uc_pdata->min_uV); > + > + ut_assert(regulator_get_value(regul_dev) == uc_pdata->min_uV); > + > + ut_assertok(regulator_set_value(regul_dev, uc_pdata->max_uV)); > + ut_asserteq(sandbox_voltd->voltage_uv, uc_pdata->max_uV); > + > + ut_assert(regulator_get_value(regul_dev) == uc_pdata->max_uV); > + > + /* Enable/disable SCMI voltage domains */ > + ut_assertok(regulator_set_enable(scmi_devices->regul[0], false)); > + ut_assertok(regulator_set_enable(scmi_devices->regul[1], false)); > + ut_assert(!scmi_ctx->agent[0]->voltd[0].enabled); > + ut_assert(!scmi_ctx->agent[0]->voltd[1].enabled); > + > + ut_assertok(regulator_set_enable(scmi_devices->regul[0], true)); > + ut_assert(scmi_ctx->agent[0]->voltd[0].enabled); > + ut_assert(!scmi_ctx->agent[0]->voltd[1].enabled); You might add a local variable for this common scmi_ctx->agent[0] > + > + ut_assertok(regulator_set_enable(scmi_devices->regul[1], true)); > + ut_assert(scmi_ctx->agent[0]->voltd[0].enabled); > + ut_assert(scmi_ctx->agent[0]->voltd[1].enabled); > + > + ut_assertok(regulator_set_enable(scmi_devices->regul[0], false)); > + ut_assert(!scmi_ctx->agent[0]->voltd[0].enabled); > + ut_assert(scmi_ctx->agent[0]->voltd[1].enabled); > + > + return release_sandbox_scmi_test_devices(uts, dev); > +} > +DM_TEST(dm_test_scmi_voltage_domains, UT_TESTF_SCAN_FDT); > -- > 2.17.1 > Regards, Simon
On 2/19/21 10:33 PM, Etienne Carriere wrote: > Implement sandbox regulator devices for SCMI voltage domains > and test them in DM scmi tests. > > Signed-off-by: Etienne Carriere <etienne.carriere@linaro.org> Reviewed-by: Jaehoon Chung <jh80.chung@samsung.com> Best Regards, Jaehoon Chung > --- > Changes in v2: > - don't test IS_ENABLED(CONFIG_DM_REGULATOR_SCMI) in test/dm/scmi.c, > it's expected enabled when CONFIG_FIRMWARE_SCMI is enabled in sandbox. > --- > arch/sandbox/dts/test.dts | 23 +++ > arch/sandbox/include/asm/scmi_test.h | 20 ++ > configs/sandbox_defconfig | 1 + > drivers/firmware/scmi/sandbox-scmi_agent.c | 203 ++++++++++++++++++- > drivers/firmware/scmi/sandbox-scmi_devices.c | 25 ++- > test/dm/scmi.c | 58 ++++++ > 6 files changed, 327 insertions(+), 3 deletions(-) > > diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts > index e95f4631b..14d6983e7 100644 > --- a/arch/sandbox/dts/test.dts > +++ b/arch/sandbox/dts/test.dts > @@ -451,6 +451,27 @@ > reg = <0x16>; > #reset-cells = <1>; > }; > + > + protocol@17 { > + reg = <0x17>; > + > + regulators { > + #address-cells = <1>; > + #size-cells = <0>; > + > + regul0_scmi0: reg@0 { > + reg = <0>; > + regulator-name = "sandbox-voltd0"; > + regulator-min-microvolt = <1100000>; > + regulator-max-microvolt = <3300000>; > + }; > + regul1_scmi0: reg@1 { > + reg = <0x1>; > + regulator-name = "sandbox-voltd1"; > + regulator-min-microvolt = <1800000>; > + }; > + }; > + }; > }; > > sandbox-scmi-agent@1 { > @@ -1217,6 +1238,8 @@ > compatible = "sandbox,scmi-devices"; > clocks = <&clk_scmi0 7>, <&clk_scmi0 3>, <&clk_scmi1 1>; > resets = <&reset_scmi0 3>; > + regul0-supply = <®ul0_scmi0>; > + regul1-supply = <®ul1_scmi0>; > }; > > pinctrl { > diff --git a/arch/sandbox/include/asm/scmi_test.h b/arch/sandbox/include/asm/scmi_test.h > index 3e8b0068f..9b7031531 100644 > --- a/arch/sandbox/include/asm/scmi_test.h > +++ b/arch/sandbox/include/asm/scmi_test.h > @@ -31,6 +31,18 @@ struct sandbox_scmi_reset { > bool asserted; > }; > > +/** > + * struct sandbox_scmi_voltd - Simulated voltage regulator exposed by SCMI > + * @id: Identifier of the voltage domain used in the SCMI protocol > + * @enabled: Regulator state: true if on, false if off > + * @voltage_uv: Regulator current voltage in microvoltd (uV) > + */ > +struct sandbox_scmi_voltd { > + uint id; > + bool enabled; > + int voltage_uv; > +}; > + > /** > * struct sandbox_scmi_agent - Simulated SCMI service seen by SCMI agent > * @idx: Identifier for the SCMI agent, its index > @@ -38,6 +50,8 @@ struct sandbox_scmi_reset { > * @clk_count: Simulated clocks array size > * @clk: Simulated reset domains > * @clk_count: Simulated reset domains array size > + * @voltd: Simulated voltage domains (regulators) > + * @voltd_count: Simulated voltage domains array size > */ > struct sandbox_scmi_agent { > uint idx; > @@ -45,6 +59,8 @@ struct sandbox_scmi_agent { > size_t clk_count; > struct sandbox_scmi_reset *reset; > size_t reset_count; > + struct sandbox_scmi_voltd *voltd; > + size_t voltd_count; > }; > > /** > @@ -63,12 +79,16 @@ struct sandbox_scmi_service { > * @clk_count: Number of clock devices probed > * @reset: Array the reset controller devices > * @reset_count: Number of reset controller devices probed > + * @regul: Array regulator devices > + * @regul_count: Number of regulator devices probed > */ > struct sandbox_scmi_devices { > struct clk *clk; > size_t clk_count; > struct reset_ctl *reset; > size_t reset_count; > + struct udevice **regul; > + size_t regul_count; > }; > > #ifdef CONFIG_SCMI_FIRMWARE > diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig > index 0c7674efc..790158445 100644 > --- a/configs/sandbox_defconfig > +++ b/configs/sandbox_defconfig > @@ -214,6 +214,7 @@ CONFIG_DM_REGULATOR_FIXED=y > CONFIG_REGULATOR_RK8XX=y > CONFIG_REGULATOR_S5M8767=y > CONFIG_DM_REGULATOR_SANDBOX=y > +CONFIG_DM_REGULATOR_SCMI=y > CONFIG_REGULATOR_TPS65090=y > CONFIG_DM_PWM=y > CONFIG_PWM_SANDBOX=y > diff --git a/drivers/firmware/scmi/sandbox-scmi_agent.c b/drivers/firmware/scmi/sandbox-scmi_agent.c > index 35de68c75..3eafc49bd 100644 > --- a/drivers/firmware/scmi/sandbox-scmi_agent.c > +++ b/drivers/firmware/scmi/sandbox-scmi_agent.c > @@ -19,14 +19,15 @@ > * SCMI protocols embedded in U-Boot. Currently: > * - SCMI clock protocol: emulate 2 agents each exposing few clocks > * - SCMI reset protocol: emulate 1 agents each exposing a reset > + * - SCMI voltage domain protocol: emulate 1 agent exposing 2 regulators > * > - * Agent #0 simulates 2 clocks and 1 reset domain. > + * Agent #0 simulates 2 clocks, 1 reset domain and 1 voltage domain. > * See IDs in scmi0_clk[]/scmi0_reset[] 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 and reset levels down. > + * All clocks and regulators are default disabled and reset controller down. > * > * This Driver exports sandbox_scmi_service_ct() for the test sequence to > * get the state of the simulated services (clock state, rate, ...) and > @@ -45,6 +46,11 @@ static struct sandbox_scmi_reset scmi0_reset[] = { > { .id = 3 }, > }; > > +static struct sandbox_scmi_voltd scmi0_voltd[] = { > + { .id = 0, .voltage_uv = 3300000 }, > + { .id = 1, .voltage_uv = 1800000 }, > +}; > + > static struct sandbox_scmi_clk scmi1_clk[] = { > { .id = 1, .rate = 44 }, > }; > @@ -81,6 +87,13 @@ static void debug_print_agent_state(struct udevice *dev, char *str) > agent->reset_count, > agent->reset_count ? agent->reset[0].asserted : -1, > agent->reset_count > 1 ? agent->reset[1].asserted : -1); > + dev_dbg(dev, " scmi%u_voltd (%zu): %u/%d, %u/%d, ...\n", > + agent->idx, > + agent->voltd_count, > + agent->voltd_count ? agent->voltd[0].enabled : -1, > + agent->voltd_count ? agent->voltd[0].voltage_uv : -1, > + agent->voltd_count ? agent->voltd[1].enabled : -1, > + agent->voltd_count ? agent->voltd[1].voltage_uv : -1); > }; > > static struct sandbox_scmi_clk *get_scmi_clk_state(uint agent_id, uint clock_id) > @@ -123,6 +136,20 @@ static struct sandbox_scmi_reset *get_scmi_reset_state(uint agent_id, > return NULL; > } > > +static struct sandbox_scmi_voltd *get_scmi_voltd_state(uint agent_id, > + uint domain_id) > +{ > + size_t n; > + > + if (agent_id == 0) { > + for (n = 0; n < ARRAY_SIZE(scmi0_voltd); n++) > + if (scmi0_voltd[n].id == domain_id) > + return scmi0_voltd + n; > + } > + > + return NULL; > +} > + > /* > * Sandbox SCMI agent ops > */ > @@ -290,6 +317,160 @@ static int sandbox_scmi_rd_reset(struct udevice *dev, struct scmi_msg *msg) > return 0; > } > > +static int sandbox_scmi_voltd_attribs(struct udevice *dev, struct scmi_msg *msg) > +{ > + struct sandbox_scmi_agent *agent = dev_get_priv(dev); > + struct scmi_voltd_attr_in *in = NULL; > + struct scmi_voltd_attr_out *out = NULL; > + struct sandbox_scmi_voltd *voltd_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_voltd_attr_in *)msg->in_msg; > + out = (struct scmi_voltd_attr_out *)msg->out_msg; > + > + voltd_state = get_scmi_voltd_state(agent->idx, in->domain_id); > + if (!voltd_state) { > + dev_err(dev, "Unexpected domain ID %u\n", in->domain_id); > + > + out->status = SCMI_NOT_FOUND; > + } else { > + memset(out, 0, sizeof(*out)); > + snprintf(out->name, sizeof(out->name), "regu%u", in->domain_id); > + > + out->status = SCMI_SUCCESS; > + } > + > + return 0; > +} > + > +static int sandbox_scmi_voltd_config_set(struct udevice *dev, > + struct scmi_msg *msg) > +{ > + struct sandbox_scmi_agent *agent = dev_get_priv(dev); > + struct scmi_voltd_config_set_in *in = NULL; > + struct scmi_voltd_config_set_out *out = NULL; > + struct sandbox_scmi_voltd *voltd_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_voltd_config_set_in *)msg->in_msg; > + out = (struct scmi_voltd_config_set_out *)msg->out_msg; > + > + voltd_state = get_scmi_voltd_state(agent->idx, in->domain_id); > + if (!voltd_state) { > + dev_err(dev, "Unexpected domain ID %u\n", in->domain_id); > + > + out->status = SCMI_NOT_FOUND; > + } else if (in->config & ~SCMI_VOLTD_CONFIG_MASK) { > + dev_err(dev, "Invalid config value 0x%x\n", in->config); > + > + out->status = SCMI_INVALID_PARAMETERS; > + } else if (in->config != SCMI_VOLTD_CONFIG_ON && > + in->config != SCMI_VOLTD_CONFIG_OFF) { > + dev_err(dev, "Unexpected custom value 0x%x\n", in->config); > + > + out->status = SCMI_INVALID_PARAMETERS; > + } else { > + voltd_state->enabled = in->config == SCMI_VOLTD_CONFIG_ON; > + out->status = SCMI_SUCCESS; > + } > + > + return 0; > +} > + > +static int sandbox_scmi_voltd_config_get(struct udevice *dev, > + struct scmi_msg *msg) > +{ > + struct sandbox_scmi_agent *agent = dev_get_priv(dev); > + struct scmi_voltd_config_get_in *in = NULL; > + struct scmi_voltd_config_get_out *out = NULL; > + struct sandbox_scmi_voltd *voltd_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_voltd_config_get_in *)msg->in_msg; > + out = (struct scmi_voltd_config_get_out *)msg->out_msg; > + > + voltd_state = get_scmi_voltd_state(agent->idx, in->domain_id); > + if (!voltd_state) { > + dev_err(dev, "Unexpected domain ID %u\n", in->domain_id); > + > + out->status = SCMI_NOT_FOUND; > + } else { > + if (voltd_state->enabled) > + out->config = SCMI_VOLTD_CONFIG_ON; > + else > + out->config = SCMI_VOLTD_CONFIG_OFF; > + > + out->status = SCMI_SUCCESS; > + } > + > + return 0; > +} > + > +static int sandbox_scmi_voltd_level_set(struct udevice *dev, > + struct scmi_msg *msg) > +{ > + struct sandbox_scmi_agent *agent = dev_get_priv(dev); > + struct scmi_voltd_level_set_in *in = NULL; > + struct scmi_voltd_level_set_out *out = NULL; > + struct sandbox_scmi_voltd *voltd_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_voltd_level_set_in *)msg->in_msg; > + out = (struct scmi_voltd_level_set_out *)msg->out_msg; > + > + voltd_state = get_scmi_voltd_state(agent->idx, in->domain_id); > + if (!voltd_state) { > + dev_err(dev, "Unexpected domain ID %u\n", in->domain_id); > + > + out->status = SCMI_NOT_FOUND; > + } else { > + voltd_state->voltage_uv = in->voltage_level; > + out->status = SCMI_SUCCESS; > + } > + > + return 0; > +} > + > +static int sandbox_scmi_voltd_level_get(struct udevice *dev, > + struct scmi_msg *msg) > +{ > + struct sandbox_scmi_agent *agent = dev_get_priv(dev); > + struct scmi_voltd_level_get_in *in = NULL; > + struct scmi_voltd_level_get_out *out = NULL; > + struct sandbox_scmi_voltd *voltd_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_voltd_level_get_in *)msg->in_msg; > + out = (struct scmi_voltd_level_get_out *)msg->out_msg; > + > + voltd_state = get_scmi_voltd_state(agent->idx, in->domain_id); > + if (!voltd_state) { > + dev_err(dev, "Unexpected domain ID %u\n", in->domain_id); > + > + out->status = SCMI_NOT_FOUND; > + } else { > + out->voltage_level = voltd_state->voltage_uv; > + out->status = SCMI_SUCCESS; > + } > + > + return 0; > +} > + > static int sandbox_scmi_test_process_msg(struct udevice *dev, > struct scmi_msg *msg) > { > @@ -316,6 +497,22 @@ static int sandbox_scmi_test_process_msg(struct udevice *dev, > break; > } > break; > + case SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN: > + switch (msg->message_id) { > + case SCMI_VOLTAGE_DOMAIN_ATTRIBUTES: > + return sandbox_scmi_voltd_attribs(dev, msg); > + case SCMI_VOLTAGE_DOMAIN_CONFIG_SET: > + return sandbox_scmi_voltd_config_set(dev, msg); > + case SCMI_VOLTAGE_DOMAIN_CONFIG_GET: > + return sandbox_scmi_voltd_config_get(dev, msg); > + case SCMI_VOLTAGE_DOMAIN_LEVEL_SET: > + return sandbox_scmi_voltd_level_set(dev, msg); > + case SCMI_VOLTAGE_DOMAIN_LEVEL_GET: > + return sandbox_scmi_voltd_level_get(dev, msg); > + default: > + break; > + } > + break; > case SCMI_PROTOCOL_ID_BASE: > case SCMI_PROTOCOL_ID_POWER_DOMAIN: > case SCMI_PROTOCOL_ID_SYSTEM: > @@ -367,6 +564,8 @@ static int sandbox_scmi_test_probe(struct udevice *dev) > .clk_count = ARRAY_SIZE(scmi0_clk), > .reset = scmi0_reset, > .reset_count = ARRAY_SIZE(scmi0_reset), > + .voltd = scmi0_voltd, > + .voltd_count = ARRAY_SIZE(scmi0_voltd), > }; > break; > case '1': > diff --git a/drivers/firmware/scmi/sandbox-scmi_devices.c b/drivers/firmware/scmi/sandbox-scmi_devices.c > index 1a6fafbf5..aab5782fd 100644 > --- a/drivers/firmware/scmi/sandbox-scmi_devices.c > +++ b/drivers/firmware/scmi/sandbox-scmi_devices.c > @@ -1,16 +1,18 @@ > // SPDX-License-Identifier: GPL-2.0 > /* > - * Copyright (C) 2020, Linaro Limited > + * Copyright (C) 2020-2021, Linaro Limited > */ > > #include <common.h> > #include <clk.h> > #include <dm.h> > +#include <log.h> > #include <malloc.h> > #include <reset.h> > #include <asm/io.h> > #include <asm/scmi_test.h> > #include <dm/device_compat.h> > +#include <power/regulator.h> > > /* > * Simulate to some extent a SCMI exchange. > @@ -21,16 +23,19 @@ > > #define SCMI_TEST_DEVICES_CLK_COUNT 3 > #define SCMI_TEST_DEVICES_RD_COUNT 1 > +#define SCMI_TEST_DEVICES_VOLTD_COUNT 2 > > /* > * struct sandbox_scmi_device_priv - Storage for device handles used by test > * @clk: Array of clock instances used by tests > * @reset_clt: Array of the reset controller instances used by tests > + * @regulators: Array of regulator device references used by the tests > * @devices: Resources exposed by sandbox_scmi_devices_ctx() > */ > struct sandbox_scmi_device_priv { > struct clk clk[SCMI_TEST_DEVICES_CLK_COUNT]; > struct reset_ctl reset_ctl[SCMI_TEST_DEVICES_RD_COUNT]; > + struct udevice *regulators[SCMI_TEST_DEVICES_VOLTD_COUNT]; > struct sandbox_scmi_devices devices; > }; > > @@ -74,6 +79,8 @@ static int sandbox_scmi_devices_probe(struct udevice *dev) > .clk_count = SCMI_TEST_DEVICES_CLK_COUNT, > .reset = priv->reset_ctl, > .reset_count = SCMI_TEST_DEVICES_RD_COUNT, > + .regul = priv->regulators, > + .regul_count = SCMI_TEST_DEVICES_VOLTD_COUNT, > }; > > for (n = 0; n < SCMI_TEST_DEVICES_CLK_COUNT; n++) { > @@ -92,8 +99,24 @@ static int sandbox_scmi_devices_probe(struct udevice *dev) > } > } > > + for (n = 0; n < SCMI_TEST_DEVICES_VOLTD_COUNT; n++) { > + char name[32]; > + > + ret = snprintf(name, sizeof(name), "regul%zu-supply", n); > + assert(ret >= 0 && ret < sizeof(name)); > + > + ret = device_get_supply_regulator(dev, name, > + priv->devices.regul + n); > + if (ret) { > + dev_err(dev, "%s: Failed on voltd %zu\n", __func__, n); > + goto err_regul; > + } > + } > + > return 0; > > +err_regul: > + n = SCMI_TEST_DEVICES_RD_COUNT; > err_reset: > for (; n > 0; n--) > reset_free(priv->devices.reset + n - 1); > diff --git a/test/dm/scmi.c b/test/dm/scmi.c > index be60b44b3..792410338 100644 > --- a/test/dm/scmi.c > +++ b/test/dm/scmi.c > @@ -20,6 +20,7 @@ > #include <dm/device-internal.h> > #include <dm/test.h> > #include <linux/kconfig.h> > +#include <power/regulator.h> > #include <test/ut.h> > > static int ut_assert_scmi_state_preprobe(struct unit_test_state *uts) > @@ -47,6 +48,7 @@ static int ut_assert_scmi_state_postprobe(struct unit_test_state *uts, > ut_asserteq(3, scmi_devices->clk_count); > if (IS_ENABLED(CONFIG_RESET_SCMI)) > ut_asserteq(1, scmi_devices->reset_count); > + ut_asserteq(2, scmi_devices->regul_count); > > /* State of the simulated SCMI server exposed */ > scmi_ctx = sandbox_scmi_service_ctx(); > @@ -58,6 +60,8 @@ static int ut_assert_scmi_state_postprobe(struct unit_test_state *uts, > ut_assertnonnull(scmi_ctx->agent[0]->clk); > ut_asserteq(1, scmi_ctx->agent[0]->reset_count); > ut_assertnonnull(scmi_ctx->agent[0]->reset); > + ut_asserteq(2, scmi_ctx->agent[0]->voltd_count); > + ut_assertnonnull(scmi_ctx->agent[0]->voltd); > > ut_assertnonnull(scmi_ctx->agent[1]); > ut_assertnonnull(scmi_ctx->agent[1]->clk); > @@ -201,3 +205,57 @@ static int dm_test_scmi_resets(struct unit_test_state *uts) > } > > DM_TEST(dm_test_scmi_resets, UT_TESTF_SCAN_FDT); > + > +static int dm_test_scmi_voltage_domains(struct unit_test_state *uts) > +{ > + struct sandbox_scmi_devices *scmi_devices; > + struct sandbox_scmi_service *scmi_ctx; > + struct sandbox_scmi_voltd *sandbox_voltd; > + struct dm_regulator_uclass_plat *uc_pdata; > + struct udevice *dev; > + struct udevice *regul_dev; > + > + ut_assertok(load_sandbox_scmi_test_devices(uts, &dev)); > + > + scmi_devices = sandbox_scmi_devices_ctx(dev); > + scmi_ctx = sandbox_scmi_service_ctx(); > + > + /* Set/Get an SCMI voltage domain level */ > + sandbox_voltd = &scmi_ctx->agent[0]->voltd[0]; > + regul_dev = scmi_devices->regul[0]; > + ut_assert(regul_dev); > + > + uc_pdata = dev_get_uclass_plat(regul_dev); > + ut_assert(uc_pdata); > + > + ut_assertok(regulator_set_value(regul_dev, uc_pdata->min_uV)); > + ut_asserteq(sandbox_voltd->voltage_uv, uc_pdata->min_uV); > + > + ut_assert(regulator_get_value(regul_dev) == uc_pdata->min_uV); > + > + ut_assertok(regulator_set_value(regul_dev, uc_pdata->max_uV)); > + ut_asserteq(sandbox_voltd->voltage_uv, uc_pdata->max_uV); > + > + ut_assert(regulator_get_value(regul_dev) == uc_pdata->max_uV); > + > + /* Enable/disable SCMI voltage domains */ > + ut_assertok(regulator_set_enable(scmi_devices->regul[0], false)); > + ut_assertok(regulator_set_enable(scmi_devices->regul[1], false)); > + ut_assert(!scmi_ctx->agent[0]->voltd[0].enabled); > + ut_assert(!scmi_ctx->agent[0]->voltd[1].enabled); > + > + ut_assertok(regulator_set_enable(scmi_devices->regul[0], true)); > + ut_assert(scmi_ctx->agent[0]->voltd[0].enabled); > + ut_assert(!scmi_ctx->agent[0]->voltd[1].enabled); > + > + ut_assertok(regulator_set_enable(scmi_devices->regul[1], true)); > + ut_assert(scmi_ctx->agent[0]->voltd[0].enabled); > + ut_assert(scmi_ctx->agent[0]->voltd[1].enabled); > + > + ut_assertok(regulator_set_enable(scmi_devices->regul[0], false)); > + ut_assert(!scmi_ctx->agent[0]->voltd[0].enabled); > + ut_assert(scmi_ctx->agent[0]->voltd[1].enabled); > + > + return release_sandbox_scmi_test_devices(uts, dev); > +} > +DM_TEST(dm_test_scmi_voltage_domains, UT_TESTF_SCAN_FDT); >
On Sat, 20 Feb 2021 at 12:55, Simon Glass <sjg@chromium.org> wrote: > > On Fri, 19 Feb 2021 at 06:34, Etienne Carriere > <etienne.carriere@linaro.org> wrote: > > > > Implement sandbox regulator devices for SCMI voltage domains > > and test them in DM scmi tests. > > > > Signed-off-by: Etienne Carriere <etienne.carriere@linaro.org> > > --- > > Changes in v2: > > - don't test IS_ENABLED(CONFIG_DM_REGULATOR_SCMI) in test/dm/scmi.c, > > it's expected enabled when CONFIG_FIRMWARE_SCMI is enabled in sandbox. > > --- > > arch/sandbox/dts/test.dts | 23 +++ > > arch/sandbox/include/asm/scmi_test.h | 20 ++ > > configs/sandbox_defconfig | 1 + > > drivers/firmware/scmi/sandbox-scmi_agent.c | 203 ++++++++++++++++++- > > drivers/firmware/scmi/sandbox-scmi_devices.c | 25 ++- > > test/dm/scmi.c | 58 ++++++ > > 6 files changed, 327 insertions(+), 3 deletions(-) > > Reviewed-by: Simon Glass <sjg@chromium.org> > > thought below > > [..] > > > diff --git a/test/dm/scmi.c b/test/dm/scmi.c > > index be60b44b3..792410338 100644 > > --- a/test/dm/scmi.c > > +++ b/test/dm/scmi.c > > @@ -20,6 +20,7 @@ > > #include <dm/device-internal.h> > > #include <dm/test.h> > > #include <linux/kconfig.h> > > +#include <power/regulator.h> > > #include <test/ut.h> > > > > static int ut_assert_scmi_state_preprobe(struct unit_test_state *uts) > > @@ -47,6 +48,7 @@ static int ut_assert_scmi_state_postprobe(struct unit_test_state *uts, > > ut_asserteq(3, scmi_devices->clk_count); > > if (IS_ENABLED(CONFIG_RESET_SCMI)) > > ut_asserteq(1, scmi_devices->reset_count); > > + ut_asserteq(2, scmi_devices->regul_count); > > > > /* State of the simulated SCMI server exposed */ > > scmi_ctx = sandbox_scmi_service_ctx(); > > @@ -58,6 +60,8 @@ static int ut_assert_scmi_state_postprobe(struct unit_test_state *uts, > > ut_assertnonnull(scmi_ctx->agent[0]->clk); > > ut_asserteq(1, scmi_ctx->agent[0]->reset_count); > > ut_assertnonnull(scmi_ctx->agent[0]->reset); > > + ut_asserteq(2, scmi_ctx->agent[0]->voltd_count); > > + ut_assertnonnull(scmi_ctx->agent[0]->voltd); > > > > ut_assertnonnull(scmi_ctx->agent[1]); > > ut_assertnonnull(scmi_ctx->agent[1]->clk); > > @@ -201,3 +205,57 @@ static int dm_test_scmi_resets(struct unit_test_state *uts) > > } > > > > DM_TEST(dm_test_scmi_resets, UT_TESTF_SCAN_FDT); > > + > > +static int dm_test_scmi_voltage_domains(struct unit_test_state *uts) > > +{ > > + struct sandbox_scmi_devices *scmi_devices; > > + struct sandbox_scmi_service *scmi_ctx; > > + struct sandbox_scmi_voltd *sandbox_voltd; > > + struct dm_regulator_uclass_plat *uc_pdata; > > + struct udevice *dev; > > + struct udevice *regul_dev; > > + > > + ut_assertok(load_sandbox_scmi_test_devices(uts, &dev)); > > + > > + scmi_devices = sandbox_scmi_devices_ctx(dev); > > + scmi_ctx = sandbox_scmi_service_ctx(); > > + > > + /* Set/Get an SCMI voltage domain level */ > > + sandbox_voltd = &scmi_ctx->agent[0]->voltd[0]; > > + regul_dev = scmi_devices->regul[0]; > > + ut_assert(regul_dev); > > + > > + uc_pdata = dev_get_uclass_plat(regul_dev); > > + ut_assert(uc_pdata); > > + > > + ut_assertok(regulator_set_value(regul_dev, uc_pdata->min_uV)); > > + ut_asserteq(sandbox_voltd->voltage_uv, uc_pdata->min_uV); > > + > > + ut_assert(regulator_get_value(regul_dev) == uc_pdata->min_uV); > > + > > + ut_assertok(regulator_set_value(regul_dev, uc_pdata->max_uV)); > > + ut_asserteq(sandbox_voltd->voltage_uv, uc_pdata->max_uV); > > + > > + ut_assert(regulator_get_value(regul_dev) == uc_pdata->max_uV); > > + > > + /* Enable/disable SCMI voltage domains */ > > + ut_assertok(regulator_set_enable(scmi_devices->regul[0], false)); > > + ut_assertok(regulator_set_enable(scmi_devices->regul[1], false)); > > + ut_assert(!scmi_ctx->agent[0]->voltd[0].enabled); > > + ut_assert(!scmi_ctx->agent[0]->voltd[1].enabled); > > + > > + ut_assertok(regulator_set_enable(scmi_devices->regul[0], true)); > > + ut_assert(scmi_ctx->agent[0]->voltd[0].enabled); > > + ut_assert(!scmi_ctx->agent[0]->voltd[1].enabled); > > You might add a local variable for this common scmi_ctx->agent[0] Right, will make it more readable. I'll update that in the v3. Regards, Etienne > > > + > > + ut_assertok(regulator_set_enable(scmi_devices->regul[1], true)); > > + ut_assert(scmi_ctx->agent[0]->voltd[0].enabled); > > + ut_assert(scmi_ctx->agent[0]->voltd[1].enabled); > > + > > + ut_assertok(regulator_set_enable(scmi_devices->regul[0], false)); > > + ut_assert(!scmi_ctx->agent[0]->voltd[0].enabled); > > + ut_assert(scmi_ctx->agent[0]->voltd[1].enabled); > > + > > + return release_sandbox_scmi_test_devices(uts, dev); > > +} > > +DM_TEST(dm_test_scmi_voltage_domains, UT_TESTF_SCAN_FDT); > > -- > > 2.17.1 > > > > Regards, > Simon
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index e95f4631b..14d6983e7 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -451,6 +451,27 @@ reg = <0x16>; #reset-cells = <1>; }; + + protocol@17 { + reg = <0x17>; + + regulators { + #address-cells = <1>; + #size-cells = <0>; + + regul0_scmi0: reg@0 { + reg = <0>; + regulator-name = "sandbox-voltd0"; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <3300000>; + }; + regul1_scmi0: reg@1 { + reg = <0x1>; + regulator-name = "sandbox-voltd1"; + regulator-min-microvolt = <1800000>; + }; + }; + }; }; sandbox-scmi-agent@1 { @@ -1217,6 +1238,8 @@ compatible = "sandbox,scmi-devices"; clocks = <&clk_scmi0 7>, <&clk_scmi0 3>, <&clk_scmi1 1>; resets = <&reset_scmi0 3>; + regul0-supply = <®ul0_scmi0>; + regul1-supply = <®ul1_scmi0>; }; pinctrl { diff --git a/arch/sandbox/include/asm/scmi_test.h b/arch/sandbox/include/asm/scmi_test.h index 3e8b0068f..9b7031531 100644 --- a/arch/sandbox/include/asm/scmi_test.h +++ b/arch/sandbox/include/asm/scmi_test.h @@ -31,6 +31,18 @@ struct sandbox_scmi_reset { bool asserted; }; +/** + * struct sandbox_scmi_voltd - Simulated voltage regulator exposed by SCMI + * @id: Identifier of the voltage domain used in the SCMI protocol + * @enabled: Regulator state: true if on, false if off + * @voltage_uv: Regulator current voltage in microvoltd (uV) + */ +struct sandbox_scmi_voltd { + uint id; + bool enabled; + int voltage_uv; +}; + /** * struct sandbox_scmi_agent - Simulated SCMI service seen by SCMI agent * @idx: Identifier for the SCMI agent, its index @@ -38,6 +50,8 @@ struct sandbox_scmi_reset { * @clk_count: Simulated clocks array size * @clk: Simulated reset domains * @clk_count: Simulated reset domains array size + * @voltd: Simulated voltage domains (regulators) + * @voltd_count: Simulated voltage domains array size */ struct sandbox_scmi_agent { uint idx; @@ -45,6 +59,8 @@ struct sandbox_scmi_agent { size_t clk_count; struct sandbox_scmi_reset *reset; size_t reset_count; + struct sandbox_scmi_voltd *voltd; + size_t voltd_count; }; /** @@ -63,12 +79,16 @@ struct sandbox_scmi_service { * @clk_count: Number of clock devices probed * @reset: Array the reset controller devices * @reset_count: Number of reset controller devices probed + * @regul: Array regulator devices + * @regul_count: Number of regulator devices probed */ struct sandbox_scmi_devices { struct clk *clk; size_t clk_count; struct reset_ctl *reset; size_t reset_count; + struct udevice **regul; + size_t regul_count; }; #ifdef CONFIG_SCMI_FIRMWARE diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index 0c7674efc..790158445 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -214,6 +214,7 @@ CONFIG_DM_REGULATOR_FIXED=y CONFIG_REGULATOR_RK8XX=y CONFIG_REGULATOR_S5M8767=y CONFIG_DM_REGULATOR_SANDBOX=y +CONFIG_DM_REGULATOR_SCMI=y CONFIG_REGULATOR_TPS65090=y CONFIG_DM_PWM=y CONFIG_PWM_SANDBOX=y diff --git a/drivers/firmware/scmi/sandbox-scmi_agent.c b/drivers/firmware/scmi/sandbox-scmi_agent.c index 35de68c75..3eafc49bd 100644 --- a/drivers/firmware/scmi/sandbox-scmi_agent.c +++ b/drivers/firmware/scmi/sandbox-scmi_agent.c @@ -19,14 +19,15 @@ * SCMI protocols embedded in U-Boot. Currently: * - SCMI clock protocol: emulate 2 agents each exposing few clocks * - SCMI reset protocol: emulate 1 agents each exposing a reset + * - SCMI voltage domain protocol: emulate 1 agent exposing 2 regulators * - * Agent #0 simulates 2 clocks and 1 reset domain. + * Agent #0 simulates 2 clocks, 1 reset domain and 1 voltage domain. * See IDs in scmi0_clk[]/scmi0_reset[] 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 and reset levels down. + * All clocks and regulators are default disabled and reset controller down. * * This Driver exports sandbox_scmi_service_ct() for the test sequence to * get the state of the simulated services (clock state, rate, ...) and @@ -45,6 +46,11 @@ static struct sandbox_scmi_reset scmi0_reset[] = { { .id = 3 }, }; +static struct sandbox_scmi_voltd scmi0_voltd[] = { + { .id = 0, .voltage_uv = 3300000 }, + { .id = 1, .voltage_uv = 1800000 }, +}; + static struct sandbox_scmi_clk scmi1_clk[] = { { .id = 1, .rate = 44 }, }; @@ -81,6 +87,13 @@ static void debug_print_agent_state(struct udevice *dev, char *str) agent->reset_count, agent->reset_count ? agent->reset[0].asserted : -1, agent->reset_count > 1 ? agent->reset[1].asserted : -1); + dev_dbg(dev, " scmi%u_voltd (%zu): %u/%d, %u/%d, ...\n", + agent->idx, + agent->voltd_count, + agent->voltd_count ? agent->voltd[0].enabled : -1, + agent->voltd_count ? agent->voltd[0].voltage_uv : -1, + agent->voltd_count ? agent->voltd[1].enabled : -1, + agent->voltd_count ? agent->voltd[1].voltage_uv : -1); }; static struct sandbox_scmi_clk *get_scmi_clk_state(uint agent_id, uint clock_id) @@ -123,6 +136,20 @@ static struct sandbox_scmi_reset *get_scmi_reset_state(uint agent_id, return NULL; } +static struct sandbox_scmi_voltd *get_scmi_voltd_state(uint agent_id, + uint domain_id) +{ + size_t n; + + if (agent_id == 0) { + for (n = 0; n < ARRAY_SIZE(scmi0_voltd); n++) + if (scmi0_voltd[n].id == domain_id) + return scmi0_voltd + n; + } + + return NULL; +} + /* * Sandbox SCMI agent ops */ @@ -290,6 +317,160 @@ static int sandbox_scmi_rd_reset(struct udevice *dev, struct scmi_msg *msg) return 0; } +static int sandbox_scmi_voltd_attribs(struct udevice *dev, struct scmi_msg *msg) +{ + struct sandbox_scmi_agent *agent = dev_get_priv(dev); + struct scmi_voltd_attr_in *in = NULL; + struct scmi_voltd_attr_out *out = NULL; + struct sandbox_scmi_voltd *voltd_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_voltd_attr_in *)msg->in_msg; + out = (struct scmi_voltd_attr_out *)msg->out_msg; + + voltd_state = get_scmi_voltd_state(agent->idx, in->domain_id); + if (!voltd_state) { + dev_err(dev, "Unexpected domain ID %u\n", in->domain_id); + + out->status = SCMI_NOT_FOUND; + } else { + memset(out, 0, sizeof(*out)); + snprintf(out->name, sizeof(out->name), "regu%u", in->domain_id); + + out->status = SCMI_SUCCESS; + } + + return 0; +} + +static int sandbox_scmi_voltd_config_set(struct udevice *dev, + struct scmi_msg *msg) +{ + struct sandbox_scmi_agent *agent = dev_get_priv(dev); + struct scmi_voltd_config_set_in *in = NULL; + struct scmi_voltd_config_set_out *out = NULL; + struct sandbox_scmi_voltd *voltd_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_voltd_config_set_in *)msg->in_msg; + out = (struct scmi_voltd_config_set_out *)msg->out_msg; + + voltd_state = get_scmi_voltd_state(agent->idx, in->domain_id); + if (!voltd_state) { + dev_err(dev, "Unexpected domain ID %u\n", in->domain_id); + + out->status = SCMI_NOT_FOUND; + } else if (in->config & ~SCMI_VOLTD_CONFIG_MASK) { + dev_err(dev, "Invalid config value 0x%x\n", in->config); + + out->status = SCMI_INVALID_PARAMETERS; + } else if (in->config != SCMI_VOLTD_CONFIG_ON && + in->config != SCMI_VOLTD_CONFIG_OFF) { + dev_err(dev, "Unexpected custom value 0x%x\n", in->config); + + out->status = SCMI_INVALID_PARAMETERS; + } else { + voltd_state->enabled = in->config == SCMI_VOLTD_CONFIG_ON; + out->status = SCMI_SUCCESS; + } + + return 0; +} + +static int sandbox_scmi_voltd_config_get(struct udevice *dev, + struct scmi_msg *msg) +{ + struct sandbox_scmi_agent *agent = dev_get_priv(dev); + struct scmi_voltd_config_get_in *in = NULL; + struct scmi_voltd_config_get_out *out = NULL; + struct sandbox_scmi_voltd *voltd_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_voltd_config_get_in *)msg->in_msg; + out = (struct scmi_voltd_config_get_out *)msg->out_msg; + + voltd_state = get_scmi_voltd_state(agent->idx, in->domain_id); + if (!voltd_state) { + dev_err(dev, "Unexpected domain ID %u\n", in->domain_id); + + out->status = SCMI_NOT_FOUND; + } else { + if (voltd_state->enabled) + out->config = SCMI_VOLTD_CONFIG_ON; + else + out->config = SCMI_VOLTD_CONFIG_OFF; + + out->status = SCMI_SUCCESS; + } + + return 0; +} + +static int sandbox_scmi_voltd_level_set(struct udevice *dev, + struct scmi_msg *msg) +{ + struct sandbox_scmi_agent *agent = dev_get_priv(dev); + struct scmi_voltd_level_set_in *in = NULL; + struct scmi_voltd_level_set_out *out = NULL; + struct sandbox_scmi_voltd *voltd_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_voltd_level_set_in *)msg->in_msg; + out = (struct scmi_voltd_level_set_out *)msg->out_msg; + + voltd_state = get_scmi_voltd_state(agent->idx, in->domain_id); + if (!voltd_state) { + dev_err(dev, "Unexpected domain ID %u\n", in->domain_id); + + out->status = SCMI_NOT_FOUND; + } else { + voltd_state->voltage_uv = in->voltage_level; + out->status = SCMI_SUCCESS; + } + + return 0; +} + +static int sandbox_scmi_voltd_level_get(struct udevice *dev, + struct scmi_msg *msg) +{ + struct sandbox_scmi_agent *agent = dev_get_priv(dev); + struct scmi_voltd_level_get_in *in = NULL; + struct scmi_voltd_level_get_out *out = NULL; + struct sandbox_scmi_voltd *voltd_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_voltd_level_get_in *)msg->in_msg; + out = (struct scmi_voltd_level_get_out *)msg->out_msg; + + voltd_state = get_scmi_voltd_state(agent->idx, in->domain_id); + if (!voltd_state) { + dev_err(dev, "Unexpected domain ID %u\n", in->domain_id); + + out->status = SCMI_NOT_FOUND; + } else { + out->voltage_level = voltd_state->voltage_uv; + out->status = SCMI_SUCCESS; + } + + return 0; +} + static int sandbox_scmi_test_process_msg(struct udevice *dev, struct scmi_msg *msg) { @@ -316,6 +497,22 @@ static int sandbox_scmi_test_process_msg(struct udevice *dev, break; } break; + case SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN: + switch (msg->message_id) { + case SCMI_VOLTAGE_DOMAIN_ATTRIBUTES: + return sandbox_scmi_voltd_attribs(dev, msg); + case SCMI_VOLTAGE_DOMAIN_CONFIG_SET: + return sandbox_scmi_voltd_config_set(dev, msg); + case SCMI_VOLTAGE_DOMAIN_CONFIG_GET: + return sandbox_scmi_voltd_config_get(dev, msg); + case SCMI_VOLTAGE_DOMAIN_LEVEL_SET: + return sandbox_scmi_voltd_level_set(dev, msg); + case SCMI_VOLTAGE_DOMAIN_LEVEL_GET: + return sandbox_scmi_voltd_level_get(dev, msg); + default: + break; + } + break; case SCMI_PROTOCOL_ID_BASE: case SCMI_PROTOCOL_ID_POWER_DOMAIN: case SCMI_PROTOCOL_ID_SYSTEM: @@ -367,6 +564,8 @@ static int sandbox_scmi_test_probe(struct udevice *dev) .clk_count = ARRAY_SIZE(scmi0_clk), .reset = scmi0_reset, .reset_count = ARRAY_SIZE(scmi0_reset), + .voltd = scmi0_voltd, + .voltd_count = ARRAY_SIZE(scmi0_voltd), }; break; case '1': diff --git a/drivers/firmware/scmi/sandbox-scmi_devices.c b/drivers/firmware/scmi/sandbox-scmi_devices.c index 1a6fafbf5..aab5782fd 100644 --- a/drivers/firmware/scmi/sandbox-scmi_devices.c +++ b/drivers/firmware/scmi/sandbox-scmi_devices.c @@ -1,16 +1,18 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Copyright (C) 2020, Linaro Limited + * Copyright (C) 2020-2021, Linaro Limited */ #include <common.h> #include <clk.h> #include <dm.h> +#include <log.h> #include <malloc.h> #include <reset.h> #include <asm/io.h> #include <asm/scmi_test.h> #include <dm/device_compat.h> +#include <power/regulator.h> /* * Simulate to some extent a SCMI exchange. @@ -21,16 +23,19 @@ #define SCMI_TEST_DEVICES_CLK_COUNT 3 #define SCMI_TEST_DEVICES_RD_COUNT 1 +#define SCMI_TEST_DEVICES_VOLTD_COUNT 2 /* * struct sandbox_scmi_device_priv - Storage for device handles used by test * @clk: Array of clock instances used by tests * @reset_clt: Array of the reset controller instances used by tests + * @regulators: Array of regulator device references used by the tests * @devices: Resources exposed by sandbox_scmi_devices_ctx() */ struct sandbox_scmi_device_priv { struct clk clk[SCMI_TEST_DEVICES_CLK_COUNT]; struct reset_ctl reset_ctl[SCMI_TEST_DEVICES_RD_COUNT]; + struct udevice *regulators[SCMI_TEST_DEVICES_VOLTD_COUNT]; struct sandbox_scmi_devices devices; }; @@ -74,6 +79,8 @@ static int sandbox_scmi_devices_probe(struct udevice *dev) .clk_count = SCMI_TEST_DEVICES_CLK_COUNT, .reset = priv->reset_ctl, .reset_count = SCMI_TEST_DEVICES_RD_COUNT, + .regul = priv->regulators, + .regul_count = SCMI_TEST_DEVICES_VOLTD_COUNT, }; for (n = 0; n < SCMI_TEST_DEVICES_CLK_COUNT; n++) { @@ -92,8 +99,24 @@ static int sandbox_scmi_devices_probe(struct udevice *dev) } } + for (n = 0; n < SCMI_TEST_DEVICES_VOLTD_COUNT; n++) { + char name[32]; + + ret = snprintf(name, sizeof(name), "regul%zu-supply", n); + assert(ret >= 0 && ret < sizeof(name)); + + ret = device_get_supply_regulator(dev, name, + priv->devices.regul + n); + if (ret) { + dev_err(dev, "%s: Failed on voltd %zu\n", __func__, n); + goto err_regul; + } + } + return 0; +err_regul: + n = SCMI_TEST_DEVICES_RD_COUNT; err_reset: for (; n > 0; n--) reset_free(priv->devices.reset + n - 1); diff --git a/test/dm/scmi.c b/test/dm/scmi.c index be60b44b3..792410338 100644 --- a/test/dm/scmi.c +++ b/test/dm/scmi.c @@ -20,6 +20,7 @@ #include <dm/device-internal.h> #include <dm/test.h> #include <linux/kconfig.h> +#include <power/regulator.h> #include <test/ut.h> static int ut_assert_scmi_state_preprobe(struct unit_test_state *uts) @@ -47,6 +48,7 @@ static int ut_assert_scmi_state_postprobe(struct unit_test_state *uts, ut_asserteq(3, scmi_devices->clk_count); if (IS_ENABLED(CONFIG_RESET_SCMI)) ut_asserteq(1, scmi_devices->reset_count); + ut_asserteq(2, scmi_devices->regul_count); /* State of the simulated SCMI server exposed */ scmi_ctx = sandbox_scmi_service_ctx(); @@ -58,6 +60,8 @@ static int ut_assert_scmi_state_postprobe(struct unit_test_state *uts, ut_assertnonnull(scmi_ctx->agent[0]->clk); ut_asserteq(1, scmi_ctx->agent[0]->reset_count); ut_assertnonnull(scmi_ctx->agent[0]->reset); + ut_asserteq(2, scmi_ctx->agent[0]->voltd_count); + ut_assertnonnull(scmi_ctx->agent[0]->voltd); ut_assertnonnull(scmi_ctx->agent[1]); ut_assertnonnull(scmi_ctx->agent[1]->clk); @@ -201,3 +205,57 @@ static int dm_test_scmi_resets(struct unit_test_state *uts) } DM_TEST(dm_test_scmi_resets, UT_TESTF_SCAN_FDT); + +static int dm_test_scmi_voltage_domains(struct unit_test_state *uts) +{ + struct sandbox_scmi_devices *scmi_devices; + struct sandbox_scmi_service *scmi_ctx; + struct sandbox_scmi_voltd *sandbox_voltd; + struct dm_regulator_uclass_plat *uc_pdata; + struct udevice *dev; + struct udevice *regul_dev; + + ut_assertok(load_sandbox_scmi_test_devices(uts, &dev)); + + scmi_devices = sandbox_scmi_devices_ctx(dev); + scmi_ctx = sandbox_scmi_service_ctx(); + + /* Set/Get an SCMI voltage domain level */ + sandbox_voltd = &scmi_ctx->agent[0]->voltd[0]; + regul_dev = scmi_devices->regul[0]; + ut_assert(regul_dev); + + uc_pdata = dev_get_uclass_plat(regul_dev); + ut_assert(uc_pdata); + + ut_assertok(regulator_set_value(regul_dev, uc_pdata->min_uV)); + ut_asserteq(sandbox_voltd->voltage_uv, uc_pdata->min_uV); + + ut_assert(regulator_get_value(regul_dev) == uc_pdata->min_uV); + + ut_assertok(regulator_set_value(regul_dev, uc_pdata->max_uV)); + ut_asserteq(sandbox_voltd->voltage_uv, uc_pdata->max_uV); + + ut_assert(regulator_get_value(regul_dev) == uc_pdata->max_uV); + + /* Enable/disable SCMI voltage domains */ + ut_assertok(regulator_set_enable(scmi_devices->regul[0], false)); + ut_assertok(regulator_set_enable(scmi_devices->regul[1], false)); + ut_assert(!scmi_ctx->agent[0]->voltd[0].enabled); + ut_assert(!scmi_ctx->agent[0]->voltd[1].enabled); + + ut_assertok(regulator_set_enable(scmi_devices->regul[0], true)); + ut_assert(scmi_ctx->agent[0]->voltd[0].enabled); + ut_assert(!scmi_ctx->agent[0]->voltd[1].enabled); + + ut_assertok(regulator_set_enable(scmi_devices->regul[1], true)); + ut_assert(scmi_ctx->agent[0]->voltd[0].enabled); + ut_assert(scmi_ctx->agent[0]->voltd[1].enabled); + + ut_assertok(regulator_set_enable(scmi_devices->regul[0], false)); + ut_assert(!scmi_ctx->agent[0]->voltd[0].enabled); + ut_assert(scmi_ctx->agent[0]->voltd[1].enabled); + + return release_sandbox_scmi_test_devices(uts, dev); +} +DM_TEST(dm_test_scmi_voltage_domains, UT_TESTF_SCAN_FDT);
Implement sandbox regulator devices for SCMI voltage domains and test them in DM scmi tests. Signed-off-by: Etienne Carriere <etienne.carriere@linaro.org> --- Changes in v2: - don't test IS_ENABLED(CONFIG_DM_REGULATOR_SCMI) in test/dm/scmi.c, it's expected enabled when CONFIG_FIRMWARE_SCMI is enabled in sandbox. --- arch/sandbox/dts/test.dts | 23 +++ arch/sandbox/include/asm/scmi_test.h | 20 ++ configs/sandbox_defconfig | 1 + drivers/firmware/scmi/sandbox-scmi_agent.c | 203 ++++++++++++++++++- drivers/firmware/scmi/sandbox-scmi_devices.c | 25 ++- test/dm/scmi.c | 58 ++++++ 6 files changed, 327 insertions(+), 3 deletions(-) -- 2.17.1