From: Anup Patel Date: Tue, 13 Jul 2021 03:23:42 +0000 (+0800) Subject: lib: utils/gpio: Add generic GPIO configuration library X-Git-Tag: v1.3~475 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=36b8effe4a07bbf476deca6c8769529c69078f08;p=platform%2Fkernel%2Fopensbi-spacemit.git lib: utils/gpio: Add generic GPIO configuration library We add generic GPIO configuration library which is independent of hardware description format (FDT or ACPI). The OpenSBI platform support or GPIO drivers can register GPIO chip instances which can be discovered and used by different GPIO clients. Each GPIO chip instance has a unique ID which can be used by GPIO clients to lookup GPIO chip instance. Signed-off-by: Anup Patel Reviewed-by: Atish Patra --- diff --git a/include/sbi_utils/gpio/gpio.h b/include/sbi_utils/gpio/gpio.h new file mode 100644 index 0000000..167d11a --- /dev/null +++ b/include/sbi_utils/gpio/gpio.h @@ -0,0 +1,99 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2021 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel + */ + +#ifndef __GPIO_H__ +#define __GPIO_H__ + +#include + +#define GPIO_LINE_DIRECTION_IN 1 +#define GPIO_LINE_DIRECTION_OUT 0 + +/** Representation of a GPIO pin */ +struct gpio_pin { + /** Pointer to the GPIO chip */ + struct gpio_chip *chip; + /** Identification of GPIO pin within GPIO chip */ + unsigned int offset; + /** + * Additional configuration flags of the GPIO pin desired + * by GPIO clients. + * + * NOTE: GPIO chip can have custom configuration flags. + */ + unsigned int flags; +#define GPIO_FLAG_ACTIVE_LOW 0x1 +#define GPIO_FLAG_SINGLE_ENDED 0x2 +#define GPIO_FLAG_OPEN_DRAIN 0x4 +#define GPIO_FLAG_TRANSITORY 0x8 +#define GPIO_FLAG_PULL_UP 0x10 +#define GPIO_FLAG_PULL_DOWN 0x20 +}; + +/** Representation of a GPIO chip */ +struct gpio_chip { + /** Pointer to GPIO driver owning this GPIO chip */ + void *driver; + /** Uniquie ID of the GPIO chip assigned by the driver */ + unsigned int id; + /** Number of GPIOs supported by the GPIO chip */ + unsigned int ngpio; + /** + * Get current direction of GPIO pin + * + * @return 0=output, 1=input, or negative error + */ + int (*get_direction)(struct gpio_pin *gp); + /** + * Set input direction of GPIO pin + * + * @return 0 on success and negative error code on failure + */ + int (*direction_input)(struct gpio_pin *gp); + /** + * Set output direction of GPIO pin with given output value + * + * @return 0 on success and negative error code on failure + */ + int (*direction_output)(struct gpio_pin *gp, int value); + /** + * Get current value of GPIO pin + * + * @return 0=low, 1=high, or negative error + */ + int (*get)(struct gpio_pin *gp); + /** Set output value for GPIO pin */ + void (*set)(struct gpio_pin *gp, int value); +}; + +/** Find a registered GPIO chip */ +struct gpio_chip *gpio_chip_find(unsigned int id); + +/** Register GPIO chip */ +int gpio_chip_add(struct gpio_chip *gc); + +/** Un-register GPIO chip */ +void gpio_chip_remove(struct gpio_chip *gc); + +/** Get current direction of GPIO pin */ +int gpio_get_direction(struct gpio_pin *gp); + +/** Set input direction of GPIO pin */ +int gpio_direction_input(struct gpio_pin *gp); + +/** Set output direction of GPIO pin */ +int gpio_direction_output(struct gpio_pin *gp, int value); + +/** Get current value of GPIO pin */ +int gpio_get(struct gpio_pin *gp); + +/** Set output value of GPIO pin */ +int gpio_set(struct gpio_pin *gp, int value); + +#endif diff --git a/lib/utils/gpio/gpio.c b/lib/utils/gpio/gpio.c new file mode 100644 index 0000000..fb30c0f --- /dev/null +++ b/lib/utils/gpio/gpio.c @@ -0,0 +1,116 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2021 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel + */ + +#include +#include + +#define GPIO_CHIP_MAX 16 + +static struct gpio_chip *gc_array[GPIO_CHIP_MAX]; + +struct gpio_chip *gpio_chip_find(unsigned int id) +{ + unsigned int i; + struct gpio_chip *ret = NULL; + + for (i = 0; i < GPIO_CHIP_MAX; i++) { + if (gc_array[i] && gc_array[i]->id == id) { + ret = gc_array[i]; + break; + } + } + + return ret; +} + +int gpio_chip_add(struct gpio_chip *gc) +{ + int i, ret = SBI_ENOSPC; + + if (!gc) + return SBI_EINVAL; + if (gpio_chip_find(gc->id)) + return SBI_EALREADY; + + for (i = 0; i < GPIO_CHIP_MAX; i++) { + if (!gc_array[i]) { + gc_array[i] = gc; + ret = 0; + break; + } + } + + return ret; +} + +void gpio_chip_remove(struct gpio_chip *gc) +{ + int i; + + if (!gc) + return; + + for (i = 0; i < GPIO_CHIP_MAX; i++) { + if (gc_array[i] == gc) { + gc_array[i] = NULL; + break; + } + } +} + +int gpio_get_direction(struct gpio_pin *gp) +{ + if (!gp || !gp->chip || (gp->chip->ngpio <= gp->offset)) + return SBI_EINVAL; + if (!gp->chip->get_direction) + return SBI_ENOSYS; + + return gp->chip->get_direction(gp); +} + +int gpio_direction_input(struct gpio_pin *gp) +{ + if (!gp || !gp->chip || (gp->chip->ngpio <= gp->offset)) + return SBI_EINVAL; + if (!gp->chip->direction_input) + return SBI_ENOSYS; + + return gp->chip->direction_input(gp); +} + +int gpio_direction_output(struct gpio_pin *gp, int value) +{ + if (!gp || !gp->chip || (gp->chip->ngpio <= gp->offset)) + return SBI_EINVAL; + if (!gp->chip->direction_output) + return SBI_ENOSYS; + + return gp->chip->direction_output(gp, value); +} + +int gpio_get(struct gpio_pin *gp) +{ + if (!gp || !gp->chip || (gp->chip->ngpio <= gp->offset)) + return SBI_EINVAL; + if (!gp->chip->get) + return SBI_ENOSYS; + + return gp->chip->get(gp); +} + +int gpio_set(struct gpio_pin *gp, int value) +{ + if (!gp || !gp->chip || (gp->chip->ngpio <= gp->offset)) + return SBI_EINVAL; + if (!gp->chip->set) + return SBI_ENOSYS; + + gp->chip->set(gp, value); + return 0; +} diff --git a/lib/utils/gpio/objects.mk b/lib/utils/gpio/objects.mk new file mode 100644 index 0000000..e99a895 --- /dev/null +++ b/lib/utils/gpio/objects.mk @@ -0,0 +1,10 @@ +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2021 Western Digital Corporation or its affiliates. +# +# Authors: +# Anup Patel +# + +libsbiutils-objs-y += gpio/gpio.o