]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
sandbox: cros-ec: Add tests for the Chromium OS EC PWM driver
authorAlper Nebi Yasak <alpernebiyasak@gmail.com>
Wed, 19 May 2021 16:33:31 +0000 (19:33 +0300)
committerSimon Glass <sjg@chromium.org>
Tue, 6 Jul 2021 16:38:03 +0000 (10:38 -0600)
This patch adds a limited pulse-width modulator to sandbox's Chromium OS
Embedded Controller emulation. The emulated PWM device supports multiple
channels but can only set a duty cycle for each, as the actual EC
doesn't expose any functionality or information other than that. Though
the EC supports specifying the PWM channel by its type (e.g. display
backlight, keyboard backlight), this is not implemented in the emulation
as nothing in U-Boot uses this type specification.

This emulated PWM device is then used to test the Chromium OS PWM driver
in sandbox. Adding the required device node to the sandbox test
device-tree unfortunately makes it the first PWM device, so this also
touches some other tests to make sure they still use the sandbox PWM.

Signed-off-by: Alper Nebi Yasak <alpernebiyasak@gmail.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
13 files changed:
arch/sandbox/dts/test.dts
arch/sandbox/include/asm/test.h
configs/sandbox64_defconfig
configs/sandbox_defconfig
configs/sandbox_flattree_defconfig
configs/sandbox_noinst_defconfig
configs/sandbox_spl_defconfig
drivers/misc/cros_ec_sandbox.c
test/cmd/pwm.c
test/dm/Makefile
test/dm/cros_ec_pwm.c [new file with mode: 0644]
test/dm/panel.c
test/dm/pwm.c

index 8e7eaf2d1504a8af1874b0df61f0483312b0d0e2..d85bb46cebaa8f572a34c695a184ff06c311607a 100644 (file)
                                size = <0x10000>;
                        };
                };
+
+               cros_ec_pwm: cros-ec-pwm {
+                       compatible = "google,cros-ec-pwm";
+                       #pwm-cells = <1>;
+               };
+
        };
 
        dsi_host: dsi_host {
index 1cb960ac240ddc6bfa023efcb8fa34fe0ace01a5..dab1a4ea01b3500ec001cba4d5cebec6e6289c83 100644 (file)
@@ -275,4 +275,14 @@ void sandbox_set_enable_memio(bool enable);
  */
 void sandbox_cros_ec_set_test_flags(struct udevice *dev, uint flags);
 
+/**
+ * sandbox_cros_ec_get_pwm_duty() - Get EC PWM config for testing purposes
+ *
+ * @dev: Device to check
+ * @index: PWM channel index
+ * @duty: Current duty cycle in 0..EC_PWM_MAX_DUTY range.
+ * @return 0 if OK, -ENOSPC if the PWM number is invalid
+ */
+int sandbox_cros_ec_get_pwm_duty(struct udevice *dev, uint index, uint *duty);
+
 #endif
index a8bb5607245d0d331babc0036bcc571aca29147f..674b6603910bb4024820017dbf3b11448fceef75 100644 (file)
@@ -188,6 +188,7 @@ CONFIG_REGULATOR_S5M8767=y
 CONFIG_DM_REGULATOR_SANDBOX=y
 CONFIG_REGULATOR_TPS65090=y
 CONFIG_DM_PWM=y
+CONFIG_PWM_CROS_EC=y
 CONFIG_PWM_SANDBOX=y
 CONFIG_RAM=y
 CONFIG_REMOTEPROC_SANDBOX=y
index f16e2d5d23dd2451b5782795d056900db77bf207..df14506b09c192c8791174ef48f2db33b4b716e7 100644 (file)
@@ -226,6 +226,7 @@ CONFIG_DM_REGULATOR_SANDBOX=y
 CONFIG_REGULATOR_TPS65090=y
 CONFIG_DM_REGULATOR_SCMI=y
 CONFIG_DM_PWM=y
+CONFIG_PWM_CROS_EC=y
 CONFIG_PWM_SANDBOX=y
 CONFIG_RAM=y
 CONFIG_REMOTEPROC_SANDBOX=y
index 1c39a545c85d3b42d5a1e5fe429a21d40c916b0c..aaa6720cf9bbd56d3ffd311c90401fb05265342a 100644 (file)
@@ -165,6 +165,7 @@ CONFIG_REGULATOR_S5M8767=y
 CONFIG_DM_REGULATOR_SANDBOX=y
 CONFIG_REGULATOR_TPS65090=y
 CONFIG_DM_PWM=y
+CONFIG_PWM_CROS_EC=y
 CONFIG_PWM_SANDBOX=y
 CONFIG_RAM=y
 CONFIG_REMOTEPROC_SANDBOX=y
index 9f415cd87563265c24c42f88bba6662d2985608e..3dc3a361543ef00789fc70613fe46375fd241cbe 100644 (file)
@@ -181,6 +181,7 @@ CONFIG_REGULATOR_S5M8767=y
 CONFIG_DM_REGULATOR_SANDBOX=y
 CONFIG_REGULATOR_TPS65090=y
 CONFIG_DM_PWM=y
+CONFIG_PWM_CROS_EC=y
 CONFIG_PWM_SANDBOX=y
 CONFIG_RAM=y
 CONFIG_REMOTEPROC_SANDBOX=y
index 8bc1373ec31c6daf2e59c8e186a5450054d77546..c7d15de93918210d49cafa74a3ab0deccd4dfa8f 100644 (file)
@@ -183,6 +183,7 @@ CONFIG_REGULATOR_S5M8767=y
 CONFIG_DM_REGULATOR_SANDBOX=y
 CONFIG_REGULATOR_TPS65090=y
 CONFIG_DM_PWM=y
+CONFIG_PWM_CROS_EC=y
 CONFIG_PWM_SANDBOX=y
 CONFIG_RAM=y
 CONFIG_REMOTEPROC_SANDBOX=y
index bc01df0904eb46b9f22878744ba4312d9b054541..db5e3b0f51a27cb443a8e95223fc6f70a8ee2d9c 100644 (file)
@@ -64,6 +64,7 @@ struct ec_keymatrix_entry {
 
 enum {
        VSTORE_SLOT_COUNT       = 4,
+       PWM_CHANNEL_COUNT       = 4,
 };
 
 struct vstore_slot {
@@ -71,6 +72,10 @@ struct vstore_slot {
        u8 data[EC_VSTORE_SLOT_SIZE];
 };
 
+struct ec_pwm_channel {
+       uint duty;      /* not ns, EC_PWM_MAX_DUTY = 100% */
+};
+
 /**
  * struct ec_state - Information about the EC state
  *
@@ -85,6 +90,7 @@ struct vstore_slot {
  * @recovery_req: Keyboard recovery requested
  * @test_flags: Flags that control behaviour for tests
  * @slot_locked: Locked vstore slots (mask)
+ * @pwm: Information per PWM channel
  */
 struct ec_state {
        u8 vbnv_context[EC_VBNV_BLOCK_SIZE_V2];
@@ -98,6 +104,7 @@ struct ec_state {
        bool recovery_req;
        uint test_flags;
        struct vstore_slot slot[VSTORE_SLOT_COUNT];
+       struct ec_pwm_channel pwm[PWM_CHANNEL_COUNT];
 } s_state, *g_state;
 
 /**
@@ -554,6 +561,33 @@ static int process_cmd(struct ec_state *ec,
                len = sizeof(*resp);
                break;
        }
+       case EC_CMD_PWM_GET_DUTY: {
+               const struct ec_params_pwm_get_duty *req = req_data;
+               struct ec_response_pwm_get_duty *resp = resp_data;
+               struct ec_pwm_channel *pwm;
+
+               if (req->pwm_type != EC_PWM_TYPE_GENERIC)
+                       return -EINVAL;
+               if (req->index >= PWM_CHANNEL_COUNT)
+                       return -EINVAL;
+               pwm = &ec->pwm[req->index];
+               resp->duty = pwm->duty;
+               len = sizeof(*resp);
+               break;
+       }
+       case EC_CMD_PWM_SET_DUTY: {
+               const struct ec_params_pwm_set_duty *req = req_data;
+               struct ec_pwm_channel *pwm;
+
+               if (req->pwm_type != EC_PWM_TYPE_GENERIC)
+                       return -EINVAL;
+               if (req->index >= PWM_CHANNEL_COUNT)
+                       return -EINVAL;
+               pwm = &ec->pwm[req->index];
+               pwm->duty = req->duty;
+               len = 0;
+               break;
+       }
        default:
                printf("   ** Unknown EC command %#02x\n", req_hdr->command);
                return -1;
@@ -619,6 +653,19 @@ void sandbox_cros_ec_set_test_flags(struct udevice *dev, uint flags)
        ec->test_flags = flags;
 }
 
+int sandbox_cros_ec_get_pwm_duty(struct udevice *dev, uint index, uint *duty)
+{
+       struct ec_state *ec = dev_get_priv(dev);
+       struct ec_pwm_channel *pwm;
+
+       if (index >= PWM_CHANNEL_COUNT)
+               return -ENOSPC;
+       pwm = &ec->pwm[index];
+       *duty = pwm->duty;
+
+       return 0;
+}
+
 int cros_ec_probe(struct udevice *dev)
 {
        struct ec_state *ec = dev_get_priv(dev);
index 5343af83fa34d95736ea31c9158027ca05c42c99..2fc0b5e4070460cc82d9f1debe3ed34e76d19364 100644 (file)
@@ -18,16 +18,20 @@ static int dm_test_pwm_cmd(struct unit_test_state *uts)
 {
        struct udevice *dev;
 
+       /* cros-ec-pwm */
        ut_assertok(uclass_get_device(UCLASS_PWM, 0, &dev));
        ut_assertnonnull(dev);
 
        ut_assertok(console_record_reset_enable());
 
        /* pwm <invert> <pwm_dev_num> <channel> <polarity> */
-       ut_assertok(run_command("pwm invert 0 0 1", 0));
+       /* cros-ec-pwm doesn't support invert */
+       ut_asserteq(1, run_command("pwm invert 0 0 1", 0));
+       ut_assert_nextline("error(-38)")
        ut_assert_console_end();
 
-       ut_assertok(run_command("pwm invert 0 0 0", 0));
+       ut_asserteq(1, run_command("pwm invert 0 0 0", 0));
+       ut_assert_nextline("error(-38)")
        ut_assert_console_end();
 
        /* pwm <config> <pwm_dev_num> <channel> <period_ns> <duty_ns> */
@@ -41,6 +45,30 @@ static int dm_test_pwm_cmd(struct unit_test_state *uts)
        ut_assertok(run_command("pwm disable 0 0", 0));
        ut_assert_console_end();
 
+       /* sandbox-pwm */
+       ut_assertok(uclass_get_device(UCLASS_PWM, 1, &dev));
+       ut_assertnonnull(dev);
+
+       ut_assertok(console_record_reset_enable());
+
+       /* pwm <invert> <pwm_dev_num> <channel> <polarity> */
+       ut_assertok(run_command("pwm invert 1 0 1", 0));
+       ut_assert_console_end();
+
+       ut_assertok(run_command("pwm invert 1 0 0", 0));
+       ut_assert_console_end();
+
+       /* pwm <config> <pwm_dev_num> <channel> <period_ns> <duty_ns> */
+       ut_assertok(run_command("pwm config 1 0 10 50", 0));
+       ut_assert_console_end();
+
+       /* pwm <enable/disable> <pwm_dev_num> <channel> */
+       ut_assertok(run_command("pwm enable 1 0", 0));
+       ut_assert_console_end();
+
+       ut_assertok(run_command("pwm disable 1 0", 0));
+       ut_assert_console_end();
+
        return 0;
 }
 
index c9644617a1fe17c80c7a85300f6d69c2cb0b2d06..9ef9171a1cbcdad6f1089566b3f929994ba28983 100644 (file)
@@ -30,6 +30,7 @@ obj-$(CONFIG_DM_BOOTCOUNT) += bootcount.o
 obj-$(CONFIG_CLK) += clk.o clk_ccf.o
 obj-$(CONFIG_CPU) += cpu.o
 obj-$(CONFIG_CROS_EC) += cros_ec.o
+obj-$(CONFIG_PWM_CROS_EC) += cros_ec_pwm.o
 obj-$(CONFIG_DEVRES) += devres.o
 obj-$(CONFIG_DMA) += dma.o
 obj-$(CONFIG_VIDEO_MIPI_DSI) += dsi_host.o
diff --git a/test/dm/cros_ec_pwm.c b/test/dm/cros_ec_pwm.c
new file mode 100644 (file)
index 0000000..f8d6e1e
--- /dev/null
@@ -0,0 +1,60 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#include <common.h>
+#include <cros_ec.h>
+#include <dm.h>
+#include <pwm.h>
+#include <asm/test.h>
+#include <dm/test.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+static int dm_test_cros_ec_pwm(struct unit_test_state *uts)
+{
+       struct udevice *pwm;
+       struct udevice *ec;
+       uint duty;
+
+       ut_assertok(uclass_get_device_by_name(UCLASS_PWM, "cros-ec-pwm", &pwm));
+       ut_assertnonnull(pwm);
+       ec = dev_get_parent(pwm);
+       ut_assertnonnull(ec);
+
+       ut_assertok(pwm_set_config(pwm, 0, 100, 50));
+       ut_assertok(pwm_set_enable(pwm, 0, true));
+       ut_assertok(sandbox_cros_ec_get_pwm_duty(ec, 0, &duty));
+       ut_asserteq(50 * EC_PWM_MAX_DUTY / 100, duty);
+
+       ut_assertok(pwm_set_config(pwm, 0, 15721, 2719));
+       ut_assertok(pwm_set_enable(pwm, 0, true));
+       ut_assertok(sandbox_cros_ec_get_pwm_duty(ec, 0, &duty));
+       ut_asserteq(2719 * EC_PWM_MAX_DUTY / 15721, duty);
+
+       ut_assertok(pwm_set_enable(pwm, 0, false));
+       ut_assertok(sandbox_cros_ec_get_pwm_duty(ec, 0, &duty));
+       ut_asserteq(0, duty);
+
+       ut_assertok(pwm_set_enable(pwm, 0, true));
+       ut_assertok(sandbox_cros_ec_get_pwm_duty(ec, 0, &duty));
+       ut_asserteq(2719 * EC_PWM_MAX_DUTY / 15721, duty);
+
+       ut_assertok(pwm_set_config(pwm, 1, 1000, 0));
+       ut_assertok(pwm_set_enable(pwm, 1, true));
+       ut_assertok(sandbox_cros_ec_get_pwm_duty(ec, 1, &duty));
+       ut_asserteq(0, duty);
+
+       ut_assertok(pwm_set_config(pwm, 2, 1000, 1024));
+       ut_assertok(pwm_set_enable(pwm, 2, true));
+       ut_assertok(sandbox_cros_ec_get_pwm_duty(ec, 2, &duty));
+       ut_asserteq(EC_PWM_MAX_DUTY, duty);
+
+       ut_assertok(pwm_set_config(pwm, 3, EC_PWM_MAX_DUTY, 0xABCD));
+       ut_assertok(pwm_set_enable(pwm, 3, true));
+       ut_assertok(sandbox_cros_ec_get_pwm_duty(ec, 3, &duty));
+       ut_asserteq(0xABCD, duty);
+
+       ut_asserteq(-EINVAL, pwm_set_enable(pwm, 4, true));
+
+       return 0;
+}
+DM_TEST(dm_test_cros_ec_pwm, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
index 49f5ac7169d3d052a4062af87e9c9d90f71c9a06..4d435a0d255c097f743f83e6298342693a707a68 100644 (file)
@@ -28,7 +28,7 @@ static int dm_test_panel(struct unit_test_state *uts)
        bool polarity;
 
        ut_assertok(uclass_first_device_err(UCLASS_PANEL, &dev));
-       ut_assertok(uclass_first_device_err(UCLASS_PWM, &pwm));
+       ut_assertok(uclass_get_device_by_name(UCLASS_PWM, "pwm", &pwm));
        ut_assertok(uclass_get_device(UCLASS_GPIO, 1, &gpio));
        ut_assertok(regulator_get_by_platname("VDD_EMMC_1.8V", &reg));
        ut_assertok(sandbox_pwm_get_config(pwm, 0, &period_ns, &duty_ns,
index b624cf3d6558a788091884c3ebc3fe6b2468729f..dff626c771ac468ac6e7771aa61cb0a18b9abc93 100644 (file)
@@ -20,7 +20,7 @@ static int dm_test_pwm_base(struct unit_test_state *uts)
        bool enable;
        bool polarity;
 
-       ut_assertok(uclass_get_device(UCLASS_PWM, 0, &dev));
+       ut_assertok(uclass_get_device_by_name(UCLASS_PWM, "pwm", &dev));
        ut_assertnonnull(dev);
        ut_assertok(pwm_set_config(dev, 0, 100, 50));
        ut_assertok(pwm_set_enable(dev, 0, true));
@@ -35,8 +35,10 @@ static int dm_test_pwm_base(struct unit_test_state *uts)
        ut_asserteq(period_ns, 4096);
        ut_asserteq(duty_ns, 50 * 4096 / 100);
 
+       ut_assertok(uclass_get_device(UCLASS_PWM, 0, &dev));
        ut_assertok(uclass_get_device(UCLASS_PWM, 1, &dev));
-       ut_asserteq(-ENODEV, uclass_get_device(UCLASS_PWM, 2, &dev));
+       ut_assertok(uclass_get_device(UCLASS_PWM, 2, &dev));
+       ut_asserteq(-ENODEV, uclass_get_device(UCLASS_PWM, 3, &dev));
 
        return 0;
 }