Signed-off-by: Samuel Dionne-Riel <sam...@dionne-riel.com> --- drivers/vibrator/Kconfig | 16 ++++ drivers/vibrator/Makefile | 1 + drivers/vibrator/vibrator_gpio.c | 122 +++++++++++++++++++++++++++++++ 3 files changed, 139 insertions(+) create mode 100644 drivers/vibrator/vibrator_gpio.c
diff --git a/drivers/vibrator/Kconfig b/drivers/vibrator/Kconfig index f988aa63b9..88e84ffb6c 100644 --- a/drivers/vibrator/Kconfig +++ b/drivers/vibrator/Kconfig @@ -18,4 +18,20 @@ config SPL_VIBRATOR enable this option. You will need to enable device tree in SPL for this to work. +config VIBRATOR_GPIO + bool "VIBRATOR support for GPIO-connected VIBRATORs" + depends on VIBRATOR && DM_GPIO + help + Enable support for vibration motors which are connected to GPIO lines. + These GPIOs may be on the SoC or some other device which provides GPIOs. + The GPIO driver must used driver model. vibration motors are configured + using the device tree. + +config SPL_VIBRATOR_GPIO + bool "Vibration motor support for GPIO-connected vibration motors in SPL" + depends on SPL_VIBRATOR && DM_GPIO + help + This option is an SPL-variant of the VIBRATOR_GPIO option. + See the help of VIBRATOR_GPIO for details. + endmenu diff --git a/drivers/vibrator/Makefile b/drivers/vibrator/Makefile index 326838ff7a..cc5fc14fbf 100644 --- a/drivers/vibrator/Makefile +++ b/drivers/vibrator/Makefile @@ -3,3 +3,4 @@ # Copyright (c) 2021 Samuel Dionne-Riel <sam...@dionne-riel.com> obj-y += vibrator-uclass.o +obj-$(CONFIG_$(SPL_)VIBRATOR_GPIO) += vibrator_gpio.o diff --git a/drivers/vibrator/vibrator_gpio.c b/drivers/vibrator/vibrator_gpio.c new file mode 100644 index 0000000000..95648a7231 --- /dev/null +++ b/drivers/vibrator/vibrator_gpio.c @@ -0,0 +1,122 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2021 Samuel Dionne-Riel <sam...@dionne-riel.com> + * Copyright (c) 2015 Google, Inc + * Largely derived from `drivers/led/led_gpio.c` + * Original written by Simon Glass <s...@chromium.org> + */ + +#include <common.h> +#include <dm.h> +#include <errno.h> +#include <vibrator.h> +#include <log.h> +#include <malloc.h> +#include <asm/gpio.h> +#include <dm/lists.h> + +struct vibrator_gpio_priv { + struct gpio_desc gpio; +}; + +static int gpio_vibrator_set_state(struct udevice *dev, enum vibrator_state_t state) +{ + struct vibrator_gpio_priv *priv = dev_get_priv(dev); + int ret; + + if (!dm_gpio_is_valid(&priv->gpio)) + return -EREMOTEIO; + switch (state) { + case VIBRATOR_STATE_OFF: + case VIBRATOR_STATE_ON: + break; + case VIBRATOR_STATE_TOGGLE: + ret = dm_gpio_get_value(&priv->gpio); + if (ret < 0) + return ret; + state = !ret; + break; + default: + return -ENOSYS; + } + + return dm_gpio_set_value(&priv->gpio, state); +} + +static enum vibrator_state_t gpio_vibrator_get_state(struct udevice *dev) +{ + struct vibrator_gpio_priv *priv = dev_get_priv(dev); + int ret; + + if (!dm_gpio_is_valid(&priv->gpio)) + return -EREMOTEIO; + ret = dm_gpio_get_value(&priv->gpio); + if (ret < 0) + return ret; + + return ret ? VIBRATOR_STATE_ON : VIBRATOR_STATE_OFF; +} + +static int vibrator_gpio_probe(struct udevice *dev) +{ + struct vibrator_gpio_priv *priv = dev_get_priv(dev); + int ret; + + ret = gpio_request_by_name(dev, "enable-gpios", 0, &priv->gpio, GPIOD_IS_OUT); + if (ret) + return ret; + + return 0; +} + +static int vibrator_gpio_remove(struct udevice *dev) +{ + /* + * The GPIO driver may have already been removed. We will need to + * address this more generally. + */ + if (!IS_ENABLED(CONFIG_SANDBOX)) { + struct vibrator_gpio_priv *priv = dev_get_priv(dev); + + if (dm_gpio_is_valid(&priv->gpio)) + dm_gpio_free(dev, &priv->gpio); + } + + return 0; +} + +static int vibrator_gpio_bind(struct udevice *dev) +{ + ofnode node; + struct vibrator_uc_plat *uc_plat; + const char *label; + + node = dev_ofnode(dev); + label = ofnode_get_name(node); + + uc_plat = dev_get_uclass_plat(dev); + uc_plat->label = label; + + return 0; +} + +static const struct vibrator_ops gpio_vibrator_ops = { + .set_state = gpio_vibrator_set_state, + .get_state = gpio_vibrator_get_state, +}; + +static const struct udevice_id vibrator_gpio_ids[] = { + { .compatible = "gpio-vibrator" }, + { } +}; + +U_BOOT_DRIVER(vibrator_gpio) = { + .name = "gpio_vibrator", + .id = UCLASS_VIBRATOR, + .of_match = vibrator_gpio_ids, + .ops = &gpio_vibrator_ops, + .priv_auto = sizeof(struct vibrator_gpio_priv), + .bind = vibrator_gpio_bind, + .probe = vibrator_gpio_probe, + .remove = vibrator_gpio_remove, +}; -- 2.34.0