diff mbox series

sandbox: cros-ec: Add tests for the cros-ec-pwm driver

Message ID 20210516154144.141945-1-alpernebiyasak@gmail.com
State Superseded
Delegated to: Simon Glass
Headers show
Series sandbox: cros-ec: Add tests for the cros-ec-pwm driver | expand

Commit Message

Alper Nebi Yasak May 16, 2021, 3:41 p.m. UTC
This patch lets sandbox-cros-ec emulate a limited pwm device which has
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.
Mapping non-generic EC_PWM_TYPE_* values to these emulated pwm channels
is not implemented as nothing in U-Boot uses these types.

This emulated pwm is then used to test the cros-ec-pwm driver in
sandbox. Adding the cros-ec-pwm 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>
---
This depends on a small fix [1] for cros-ec-pwm which otherwise fails to
build.

[1] https://patchwork.ozlabs.org/project/uboot/patch/20210514134840.19380-1-alpernebiyasak@gmail.com/

 arch/sandbox/dts/test.dts          |  6 +++
 arch/sandbox/include/asm/test.h    | 10 +++++
 configs/sandbox64_defconfig        |  1 +
 configs/sandbox_defconfig          |  1 +
 configs/sandbox_flattree_defconfig |  1 +
 configs/sandbox_noinst_defconfig   |  1 +
 configs/sandbox_spl_defconfig      |  1 +
 drivers/misc/cros_ec_sandbox.c     | 47 +++++++++++++++++++++++
 test/cmd/pwm.c                     | 32 +++++++++++++++-
 test/dm/Makefile                   |  1 +
 test/dm/cros_ec_pwm.c              | 60 ++++++++++++++++++++++++++++++
 test/dm/panel.c                    |  2 +-
 test/dm/pwm.c                      |  6 ++-
 13 files changed, 164 insertions(+), 5 deletions(-)
 create mode 100644 test/dm/cros_ec_pwm.c

Comments

Heinrich Schuchardt May 16, 2021, 8:05 p.m. UTC | #1
Am 16. Mai 2021 17:41:44 MESZ schrieb Alper Nebi Yasak <alpernebiyasak@gmail.com>:
>This patch lets sandbox-cros-ec emulate a limited pwm device which has
>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.
>Mapping non-generic EC_PWM_TYPE_* values to these emulated pwm channels
>is not implemented as nothing in U-Boot uses these types.

This commit messages is full of of abbreviations which makes it unclear. Please, use human readable terms.

I guess you might be talking about

Chromium OS
Embedded Controller
Pulse Width Modulation

But I am not sure.

Best regards

Heinrich

>
>This emulated pwm is then used to test the cros-ec-pwm driver in
>sandbox. Adding the cros-ec-pwm 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>
>---
>This depends on a small fix [1] for cros-ec-pwm which otherwise fails
>to
>build.
>
>[1]
>https://patchwork.ozlabs.org/project/uboot/patch/20210514134840.19380-1-alpernebiyasak@gmail.com/
>
> arch/sandbox/dts/test.dts          |  6 +++
> arch/sandbox/include/asm/test.h    | 10 +++++
> configs/sandbox64_defconfig        |  1 +
> configs/sandbox_defconfig          |  1 +
> configs/sandbox_flattree_defconfig |  1 +
> configs/sandbox_noinst_defconfig   |  1 +
> configs/sandbox_spl_defconfig      |  1 +
> drivers/misc/cros_ec_sandbox.c     | 47 +++++++++++++++++++++++
> test/cmd/pwm.c                     | 32 +++++++++++++++-
> test/dm/Makefile                   |  1 +
> test/dm/cros_ec_pwm.c              | 60 ++++++++++++++++++++++++++++++
> test/dm/panel.c                    |  2 +-
> test/dm/pwm.c                      |  6 ++-
> 13 files changed, 164 insertions(+), 5 deletions(-)
> create mode 100644 test/dm/cros_ec_pwm.c
>
>diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
>index 5ca3bc502a43..c684ff0b6db8 100644
>--- a/arch/sandbox/dts/test.dts
>+++ b/arch/sandbox/dts/test.dts
>@@ -139,6 +139,12 @@
> 				size = <0x10000>;
> 			};
> 		};
>+
>+		cros_ec_pwm: cros-ec-pwm {
>+			compatible = "google,cros-ec-pwm";
>+			#pwm-cells = <1>;
>+		};
>+
> 	};
> 
> 	dsi_host: dsi_host {
>diff --git a/arch/sandbox/include/asm/test.h
>b/arch/sandbox/include/asm/test.h
>index 1cb960ac240d..dab1a4ea01b3 100644
>--- a/arch/sandbox/include/asm/test.h
>+++ b/arch/sandbox/include/asm/test.h
>@@ -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
>diff --git a/configs/sandbox64_defconfig b/configs/sandbox64_defconfig
>index 9a373bab6fe3..188ce05cfbf1 100644
>--- a/configs/sandbox64_defconfig
>+++ b/configs/sandbox64_defconfig
>@@ -186,6 +186,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
>diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
>index bdbf714e2bd9..6c7a2f02718b 100644
>--- a/configs/sandbox_defconfig
>+++ b/configs/sandbox_defconfig
>@@ -223,6 +223,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
>diff --git a/configs/sandbox_flattree_defconfig
>b/configs/sandbox_flattree_defconfig
>index 853c9440ea02..0844d6ec23eb 100644
>--- a/configs/sandbox_flattree_defconfig
>+++ b/configs/sandbox_flattree_defconfig
>@@ -163,6 +163,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
>diff --git a/configs/sandbox_noinst_defconfig
>b/configs/sandbox_noinst_defconfig
>index c7fc98b5569a..629bde1f7ed6 100644
>--- a/configs/sandbox_noinst_defconfig
>+++ b/configs/sandbox_noinst_defconfig
>@@ -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
>diff --git a/configs/sandbox_spl_defconfig
>b/configs/sandbox_spl_defconfig
>index 87223a54d873..aa629e231753 100644
>--- a/configs/sandbox_spl_defconfig
>+++ b/configs/sandbox_spl_defconfig
>@@ -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
>diff --git a/drivers/misc/cros_ec_sandbox.c
>b/drivers/misc/cros_ec_sandbox.c
>index bc01df0904eb..db5e3b0f51a2 100644
>--- a/drivers/misc/cros_ec_sandbox.c
>+++ b/drivers/misc/cros_ec_sandbox.c
>@@ -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);
>diff --git a/test/cmd/pwm.c b/test/cmd/pwm.c
>index 5343af83fa34..2fc0b5e40704 100644
>--- a/test/cmd/pwm.c
>+++ b/test/cmd/pwm.c
>@@ -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;
> }
> 
>diff --git a/test/dm/Makefile b/test/dm/Makefile
>index c9644617a1fe..9ef9171a1cbc 100644
>--- a/test/dm/Makefile
>+++ b/test/dm/Makefile
>@@ -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
>index 000000000000..f8d6e1e6c40f
>--- /dev/null
>+++ b/test/dm/cros_ec_pwm.c
>@@ -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);
>diff --git a/test/dm/panel.c b/test/dm/panel.c
>index 49f5ac7169d3..4d435a0d255c 100644
>--- a/test/dm/panel.c
>+++ b/test/dm/panel.c
>@@ -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,
>diff --git a/test/dm/pwm.c b/test/dm/pwm.c
>index b624cf3d6558..dff626c771ac 100644
>--- a/test/dm/pwm.c
>+++ b/test/dm/pwm.c
>@@ -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;
> }
Alper Nebi Yasak May 19, 2021, 3:28 p.m. UTC | #2
On 16/05/2021 23:05, Heinrich Schuchardt wrote:
> Am 16. Mai 2021 17:41:44 MESZ schrieb Alper Nebi Yasak <alpernebiyasak@gmail.com>:
>> This patch lets sandbox-cros-ec emulate a limited pwm device which has
>> 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.
>> Mapping non-generic EC_PWM_TYPE_* values to these emulated pwm channels
>> is not implemented as nothing in U-Boot uses these types.
> 
> This commit messages is full of of abbreviations which makes it unclear. Please, use human readable terms.
> 
> I guess you might be talking about
> 
> Chromium OS
> Embedded Controller
> Pulse Width Modulation
> 
> But I am not sure.

Those are pretty much correct. I'm sending a v2 with hopefully a clearer
commit message.

> Best regards
> 
> Heinrich
> 
>>
>> This emulated pwm is then used to test the cros-ec-pwm driver in
>> sandbox. Adding the cros-ec-pwm 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>
Simon Glass May 19, 2021, 3:32 p.m. UTC | #3
On Sun, 16 May 2021 at 09:42, Alper Nebi Yasak <alpernebiyasak@gmail.com> wrote:
>
> This patch lets sandbox-cros-ec emulate a limited pwm device which has
> 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.
> Mapping non-generic EC_PWM_TYPE_* values to these emulated pwm channels
> is not implemented as nothing in U-Boot uses these types.
>
> This emulated pwm is then used to test the cros-ec-pwm driver in
> sandbox. Adding the cros-ec-pwm 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>
> ---
> This depends on a small fix [1] for cros-ec-pwm which otherwise fails to
> build.
>
> [1] https://patchwork.ozlabs.org/project/uboot/patch/20210514134840.19380-1-alpernebiyasak@gmail.com/
>
>  arch/sandbox/dts/test.dts          |  6 +++
>  arch/sandbox/include/asm/test.h    | 10 +++++
>  configs/sandbox64_defconfig        |  1 +
>  configs/sandbox_defconfig          |  1 +
>  configs/sandbox_flattree_defconfig |  1 +
>  configs/sandbox_noinst_defconfig   |  1 +
>  configs/sandbox_spl_defconfig      |  1 +
>  drivers/misc/cros_ec_sandbox.c     | 47 +++++++++++++++++++++++
>  test/cmd/pwm.c                     | 32 +++++++++++++++-
>  test/dm/Makefile                   |  1 +
>  test/dm/cros_ec_pwm.c              | 60 ++++++++++++++++++++++++++++++
>  test/dm/panel.c                    |  2 +-
>  test/dm/pwm.c                      |  6 ++-
>  13 files changed, 164 insertions(+), 5 deletions(-)
>  create mode 100644 test/dm/cros_ec_pwm.c

Reviewed-by: Simon Glass <sjg@chromium.org>
diff mbox series

Patch

diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 5ca3bc502a43..c684ff0b6db8 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -139,6 +139,12 @@ 
 				size = <0x10000>;
 			};
 		};
+
+		cros_ec_pwm: cros-ec-pwm {
+			compatible = "google,cros-ec-pwm";
+			#pwm-cells = <1>;
+		};
+
 	};
 
 	dsi_host: dsi_host {
diff --git a/arch/sandbox/include/asm/test.h b/arch/sandbox/include/asm/test.h
index 1cb960ac240d..dab1a4ea01b3 100644
--- a/arch/sandbox/include/asm/test.h
+++ b/arch/sandbox/include/asm/test.h
@@ -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
diff --git a/configs/sandbox64_defconfig b/configs/sandbox64_defconfig
index 9a373bab6fe3..188ce05cfbf1 100644
--- a/configs/sandbox64_defconfig
+++ b/configs/sandbox64_defconfig
@@ -186,6 +186,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
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index bdbf714e2bd9..6c7a2f02718b 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -223,6 +223,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
diff --git a/configs/sandbox_flattree_defconfig b/configs/sandbox_flattree_defconfig
index 853c9440ea02..0844d6ec23eb 100644
--- a/configs/sandbox_flattree_defconfig
+++ b/configs/sandbox_flattree_defconfig
@@ -163,6 +163,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
diff --git a/configs/sandbox_noinst_defconfig b/configs/sandbox_noinst_defconfig
index c7fc98b5569a..629bde1f7ed6 100644
--- a/configs/sandbox_noinst_defconfig
+++ b/configs/sandbox_noinst_defconfig
@@ -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
diff --git a/configs/sandbox_spl_defconfig b/configs/sandbox_spl_defconfig
index 87223a54d873..aa629e231753 100644
--- a/configs/sandbox_spl_defconfig
+++ b/configs/sandbox_spl_defconfig
@@ -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
diff --git a/drivers/misc/cros_ec_sandbox.c b/drivers/misc/cros_ec_sandbox.c
index bc01df0904eb..db5e3b0f51a2 100644
--- a/drivers/misc/cros_ec_sandbox.c
+++ b/drivers/misc/cros_ec_sandbox.c
@@ -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);
diff --git a/test/cmd/pwm.c b/test/cmd/pwm.c
index 5343af83fa34..2fc0b5e40704 100644
--- a/test/cmd/pwm.c
+++ b/test/cmd/pwm.c
@@ -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;
 }
 
diff --git a/test/dm/Makefile b/test/dm/Makefile
index c9644617a1fe..9ef9171a1cbc 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -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
index 000000000000..f8d6e1e6c40f
--- /dev/null
+++ b/test/dm/cros_ec_pwm.c
@@ -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);
diff --git a/test/dm/panel.c b/test/dm/panel.c
index 49f5ac7169d3..4d435a0d255c 100644
--- a/test/dm/panel.c
+++ b/test/dm/panel.c
@@ -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,
diff --git a/test/dm/pwm.c b/test/dm/pwm.c
index b624cf3d6558..dff626c771ac 100644
--- a/test/dm/pwm.c
+++ b/test/dm/pwm.c
@@ -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;
 }