All of lore.kernel.org
 help / color / mirror / Atom feed
From: Samuel Dionne-Riel <samuel@dionne-riel.com>
To: u-boot@lists.denx.de
Cc: Samuel Dionne-Riel <samuel@dionne-riel.com>
Subject: [PATCH 1/4] drivers: Introduce vibrator uclass
Date: Wed, 22 Dec 2021 17:36:04 -0500	[thread overview]
Message-ID: <20211222223607.3734687-2-samuel@dionne-riel.com> (raw)
In-Reply-To: <20211222223607.3734687-1-samuel@dionne-riel.com>

Signed-off-by: Samuel Dionne-Riel <samuel@dionne-riel.com>
---
 arch/sandbox/dts/test.dts          | 10 +++
 configs/sandbox_defconfig          |  2 +
 drivers/Kconfig                    |  2 +
 drivers/Makefile                   |  1 +
 drivers/vibrator/Kconfig           | 21 +++++++
 drivers/vibrator/Makefile          |  5 ++
 drivers/vibrator/vibrator-uclass.c | 62 +++++++++++++++++++
 include/dm/uclass-id.h             |  1 +
 include/vibrator.h                 | 87 +++++++++++++++++++++++++++
 test/dm/Makefile                   |  1 +
 test/dm/vibrator.c                 | 97 ++++++++++++++++++++++++++++++
 11 files changed, 289 insertions(+)
 create mode 100644 drivers/vibrator/Kconfig
 create mode 100644 drivers/vibrator/Makefile
 create mode 100644 drivers/vibrator/vibrator-uclass.c
 create mode 100644 include/vibrator.h
 create mode 100644 test/dm/vibrator.c

diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 2cea4a43c8..3633b8fb9f 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -1608,6 +1608,16 @@
 			compatible = "sandbox,regmap_test";
 		};
 	};
+
+	vibrator_left {
+		compatible = "gpio-vibrator";
+		enable-gpios = <&gpio_a 1 0 GPIO_ACTIVE_HIGH>;
+	};
+
+	vibrator_right {
+		compatible = "gpio-vibrator";
+		enable-gpios = <&gpio_a 2 0 GPIO_ACTIVE_HIGH>;
+	};
 };
 
 #include "sandbox_pmic.dtsi"
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index c390afe9de..43f9972178 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -273,6 +273,8 @@ CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_DOWNLOAD=y
 CONFIG_USB_ETHER=y
 CONFIG_USB_ETH_CDC=y
+CONFIG_VIBRATOR=y
+CONFIG_VIBRATOR_GPIO=y
 CONFIG_DM_VIDEO=y
 CONFIG_VIDEO_COPY=y
 CONFIG_CONSOLE_ROTATION=y
diff --git a/drivers/Kconfig b/drivers/Kconfig
index b26ca8cf70..a15674f22c 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -134,6 +134,8 @@ source "drivers/usb/Kconfig"
 
 source "drivers/ufs/Kconfig"
 
+source "drivers/vibrator/Kconfig"
+
 source "drivers/video/Kconfig"
 
 source "drivers/virtio/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index 4e7cf28440..2290d4a5d8 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -29,6 +29,7 @@ obj-$(CONFIG_$(SPL_TPL_)RTC) += rtc/
 obj-$(CONFIG_$(SPL_TPL_)SERIAL) += serial/
 obj-$(CONFIG_$(SPL_TPL_)SPI) += spi/
 obj-$(CONFIG_$(SPL_TPL_)TIMER) += timer/
+obj-$(CONFIG_$(SPL_TPL_)VIBRATOR) += vibrator/
 obj-$(CONFIG_$(SPL_TPL_)VIRTIO) += virtio/
 obj-$(CONFIG_$(SPL_)DM_MAILBOX) += mailbox/
 obj-$(CONFIG_$(SPL_)REMOTEPROC) += remoteproc/
diff --git a/drivers/vibrator/Kconfig b/drivers/vibrator/Kconfig
new file mode 100644
index 0000000000..f988aa63b9
--- /dev/null
+++ b/drivers/vibrator/Kconfig
@@ -0,0 +1,21 @@
+menu "Vibrator Feedback Support"
+
+config VIBRATOR
+	bool "Enable vibration motor support"
+	depends on DM
+	help
+	  Many boards have vibration motorss which can be used to signal status or
+	  alerts. U-Boot provides a uclass API to implement this feature. Vibration
+	  motor drivers can provide access to board-specific vibration motors. Use
+	  of the device tree for configuration is encouraged.
+
+config SPL_VIBRATOR
+	bool "Enable vibration motor support in SPL"
+	depends on SPL && SPL_DM
+	help
+	  The vibration motor subsystem adds a small amount of overhead to the image.
+	  If this is acceptable and you have a need to use vibration motors in SPL,
+	  enable this option. You will need to enable device tree in SPL
+	  for this to work.
+
+endmenu
diff --git a/drivers/vibrator/Makefile b/drivers/vibrator/Makefile
new file mode 100644
index 0000000000..326838ff7a
--- /dev/null
+++ b/drivers/vibrator/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (c) 2021 Samuel Dionne-Riel <samuel@dionne-riel.com>
+
+obj-y += vibrator-uclass.o
diff --git a/drivers/vibrator/vibrator-uclass.c b/drivers/vibrator/vibrator-uclass.c
new file mode 100644
index 0000000000..ffb6522a19
--- /dev/null
+++ b/drivers/vibrator/vibrator-uclass.c
@@ -0,0 +1,62 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2021 Samuel Dionne-Riel <samuel@dionne-riel.com>
+ * Copyright (c) 2015 Google, Inc
+ * Largely derived from `drivers/led/led-uclass.c`
+ * Original written by Simon Glass <sjg@chromium.org>
+ */
+
+#define LOG_CATEGORY UCLASS_VIBRATOR
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <vibrator.h>
+#include <dm/device-internal.h>
+#include <dm/root.h>
+#include <dm/uclass-internal.h>
+
+int vibrator_get_by_label(const char *label, struct udevice **devp)
+{
+	struct udevice *dev;
+	struct uclass *uc;
+	int ret;
+
+	ret = uclass_get(UCLASS_VIBRATOR, &uc);
+	if (ret)
+		return ret;
+	uclass_foreach_dev(dev, uc) {
+		struct vibrator_uc_plat *uc_plat = dev_get_uclass_plat(dev);
+
+		if (uc_plat->label && strcmp(label, uc_plat->label) == 0)
+			return uclass_get_device_tail(dev, 0, devp);
+	}
+
+	return -ENODEV;
+}
+
+int vibrator_set_state(struct udevice *dev, enum vibrator_state_t state)
+{
+	struct vibrator_ops *ops = vibrator_get_ops(dev);
+
+	if (!ops->set_state)
+		return -ENOSYS;
+
+	return ops->set_state(dev, state);
+}
+
+enum vibrator_state_t vibrator_get_state(struct udevice *dev)
+{
+	struct vibrator_ops *ops = vibrator_get_ops(dev);
+
+	if (!ops->get_state)
+		return -ENOSYS;
+
+	return ops->get_state(dev);
+}
+
+UCLASS_DRIVER(vibrator) = {
+	.id		= UCLASS_VIBRATOR,
+	.name		= "vibrator",
+	.per_device_plat_auto	= sizeof(struct vibrator_uc_plat),
+};
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index 0e26e1d138..265369d07b 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -125,6 +125,7 @@ enum uclass_id {
 	UCLASS_USB_DEV_GENERIC,	/* USB generic device */
 	UCLASS_USB_HUB,		/* USB hub */
 	UCLASS_USB_GADGET_GENERIC,	/* USB generic device */
+	UCLASS_VIBRATOR,	/* Vibration feedback devices (phone vibration) */
 	UCLASS_VIDEO,		/* Video or LCD device */
 	UCLASS_VIDEO_BRIDGE,	/* Video bridge, e.g. DisplayPort to LVDS */
 	UCLASS_VIDEO_CONSOLE,	/* Text console driver for video device */
diff --git a/include/vibrator.h b/include/vibrator.h
new file mode 100644
index 0000000000..9b04c7303a
--- /dev/null
+++ b/include/vibrator.h
@@ -0,0 +1,87 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2021 Samuel Dionne-Riel <samuel@dionne-riel.com>
+ * Copyright (c) 2015 Google, Inc
+ * Largely derived from `include/led.h`
+ * Original written by Simon Glass <sjg@chromium.org>
+ */
+
+#ifndef __VIBRATOR_H
+#define __VIBRATOR_H
+
+struct udevice;
+
+/**
+ * struct vibrator_uc_plat - Platform data the uclass stores about each device
+ *
+ * @label:	VIBRATOR label
+ */
+struct vibrator_uc_plat {
+	const char *label;
+};
+
+/**
+ * struct vibrator_uc_priv - Private data the uclass stores about each device
+ *
+ * @period_ms:	Flash period in milliseconds
+ */
+struct vibrator_uc_priv {
+	int period_ms;
+};
+
+enum vibrator_state_t {
+	VIBRATOR_STATE_OFF = 0,
+	VIBRATOR_STATE_ON = 1,
+	VIBRATOR_STATE_TOGGLE,
+
+	VIBRATOR_STATE_COUNT,
+};
+
+struct vibrator_ops {
+	/**
+	 * set_state() - set the state of an VIBRATOR
+	 *
+	 * @dev:	VIBRATOR device to change
+	 * @state:	VIBRATOR state to set
+	 * @return 0 if OK, -ve on error
+	 */
+	int (*set_state)(struct udevice *dev, enum vibrator_state_t state);
+
+	/**
+	 * vibrator_get_state() - get the state of an VIBRATOR
+	 *
+	 * @dev:	VIBRATOR device to change
+	 * @return VIBRATOR state vibrator_state_t, or -ve on error
+	 */
+	enum vibrator_state_t (*get_state)(struct udevice *dev);
+};
+
+#define vibrator_get_ops(dev)	((struct vibrator_ops *)(dev)->driver->ops)
+
+/**
+ * vibrator_get_by_label() - Find an VIBRATOR device by label
+ *
+ * @label:	VIBRATOR label to look up
+ * @devp:	Returns the associated device, if found
+ * @return 0 if found, -ENODEV if not found, other -ve on error
+ */
+int vibrator_get_by_label(const char *label, struct udevice **devp);
+
+/**
+ * vibrator_set_state() - set the state of an VIBRATOR
+ *
+ * @dev:	VIBRATOR device to change
+ * @state:	VIBRATOR state to set
+ * @return 0 if OK, -ve on error
+ */
+int vibrator_set_state(struct udevice *dev, enum vibrator_state_t state);
+
+/**
+ * vibrator_get_state() - get the state of an VIBRATOR
+ *
+ * @dev:	VIBRATOR device to change
+ * @return VIBRATOR state vibrator_state_t, or -ve on error
+ */
+enum vibrator_state_t vibrator_get_state(struct udevice *dev);
+
+#endif
diff --git a/test/dm/Makefile b/test/dm/Makefile
index d46552fbf3..dffed0e7fc 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -106,6 +106,7 @@ obj-$(CONFIG_TEE) += tee.o
 obj-$(CONFIG_TIMER) += timer.o
 obj-$(CONFIG_DM_USB) += usb.o
 obj-$(CONFIG_DM_VIDEO) += video.o
+obj-$(CONFIG_VIBRATOR) += vibrator.o
 obj-$(CONFIG_VIRTIO_SANDBOX) += virtio.o
 ifeq ($(CONFIG_WDT_GPIO)$(CONFIG_WDT_SANDBOX),yy)
 obj-y += wdt.o
diff --git a/test/dm/vibrator.c b/test/dm/vibrator.c
new file mode 100644
index 0000000000..ab5b548431
--- /dev/null
+++ b/test/dm/vibrator.c
@@ -0,0 +1,97 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2021 Samuel Dionne-Riel <samuel@dionne-riel.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <vibrator.h>
+#include <asm/gpio.h>
+#include <dm/test.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+/* Base test of the vibrator uclass */
+static int dm_test_vibrator_base(struct unit_test_state *uts)
+{
+	struct udevice *dev;
+
+	ut_assertok(uclass_get_device(UCLASS_VIBRATOR, 0, &dev));
+	ut_assertok(uclass_get_device(UCLASS_VIBRATOR, 1, &dev));
+	ut_asserteq(-ENODEV, uclass_get_device(UCLASS_VIBRATOR, 2, &dev));
+
+	return 0;
+}
+DM_TEST(dm_test_vibrator_base, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
+
+/* Test of the vibrator uclass using the vibrator_gpio driver */
+static int dm_test_vibrator_gpio(struct unit_test_state *uts)
+{
+	const int offset = 1;
+	struct udevice *dev, *gpio;
+
+	/*
+	 * Check that we can manipulate a vibration motor. Vibrator 1 is connected to GPIO
+	 * bank gpio_a, offset 1.
+	 */
+	ut_assertok(uclass_get_device(UCLASS_VIBRATOR, 0, &dev));
+	ut_assertok(uclass_get_device(UCLASS_GPIO, 1, &gpio));
+	ut_asserteq(0, sandbox_gpio_get_value(gpio, offset));
+	ut_assertok(vibrator_set_state(dev, VIBRATOR_STATE_ON));
+	ut_asserteq(1, sandbox_gpio_get_value(gpio, offset));
+	ut_asserteq(VIBRATOR_STATE_ON, vibrator_get_state(dev));
+
+	ut_assertok(vibrator_set_state(dev, VIBRATOR_STATE_OFF));
+	ut_asserteq(0, sandbox_gpio_get_value(gpio, offset));
+	ut_asserteq(VIBRATOR_STATE_OFF, vibrator_get_state(dev));
+
+	return 0;
+}
+DM_TEST(dm_test_vibrator_gpio, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
+
+/* Test that we can toggle vibration motors */
+static int dm_test_vibrator_toggle(struct unit_test_state *uts)
+{
+	const int offset = 1;
+	struct udevice *dev, *gpio;
+
+	/*
+	 * Check that we can manipulate a vibration motor. Vibrator 1 is connected to GPIO
+	 * bank gpio_a, offset 1.
+	 */
+	ut_assertok(uclass_get_device(UCLASS_VIBRATOR, 0, &dev));
+	ut_assertok(uclass_get_device(UCLASS_GPIO, 1, &gpio));
+	ut_asserteq(0, sandbox_gpio_get_value(gpio, offset));
+	ut_assertok(vibrator_set_state(dev, VIBRATOR_STATE_TOGGLE));
+	ut_asserteq(1, sandbox_gpio_get_value(gpio, offset));
+	ut_asserteq(VIBRATOR_STATE_ON, vibrator_get_state(dev));
+
+	ut_assertok(vibrator_set_state(dev, VIBRATOR_STATE_TOGGLE));
+	ut_asserteq(0, sandbox_gpio_get_value(gpio, offset));
+	ut_asserteq(VIBRATOR_STATE_OFF, vibrator_get_state(dev));
+
+	return 0;
+}
+DM_TEST(dm_test_vibrator_toggle, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
+
+/* Test obtaining a vibration motor by label */
+static int dm_test_vibrator_label(struct unit_test_state *uts)
+{
+	struct udevice *dev, *cmp;
+
+	ut_assertok(vibrator_get_by_label("vibrator_left", &dev));
+	ut_asserteq(1, device_active(dev));
+	ut_assertok(uclass_get_device(UCLASS_VIBRATOR, 0, &cmp));
+	ut_asserteq_ptr(dev, cmp);
+
+	ut_assertok(vibrator_get_by_label("vibrator_right", &dev));
+	ut_asserteq(1, device_active(dev));
+	ut_assertok(uclass_get_device(UCLASS_VIBRATOR, 1, &cmp));
+	ut_asserteq_ptr(dev, cmp);
+
+	ut_asserteq(-ENODEV, vibrator_get_by_label("doesnotexist", &dev));
+
+	return 0;
+}
+DM_TEST(dm_test_vibrator_label, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
+
-- 
2.34.0


  reply	other threads:[~2021-12-22 22:37 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-12-22 22:36 [PATCH 0/4] Add vibration motor support to U-Boot Samuel Dionne-Riel
2021-12-22 22:36 ` Samuel Dionne-Riel [this message]
2021-12-28  8:34   ` [PATCH 1/4] drivers: Introduce vibrator uclass Simon Glass
2022-01-28 22:39   ` Tom Rini
2021-12-22 22:36 ` [PATCH 2/4] vibrator: Add vibrator_gpio driver Samuel Dionne-Riel
2021-12-28  8:34   ` Simon Glass
2021-12-22 22:36 ` [PATCH 3/4] cmd: Add vibrator command Samuel Dionne-Riel
2021-12-28  8:34   ` Simon Glass
2021-12-22 22:36 ` [PATCH 4/4] pinephone_defconfig: Add gpio vibrator support Samuel Dionne-Riel

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20211222223607.3734687-2-samuel@dionne-riel.com \
    --to=samuel@dionne-riel.com \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.