diff mbox series

[v4,2/5] lib: utils/gpio: Add generic GPIO configuration library

Message ID 20210713032345.2571-3-green.wan@sifive.com
State Accepted
Headers show
Series GPIO reset support | expand

Commit Message

Green Wan July 13, 2021, 3:23 a.m. UTC
From: Anup Patel <anup.patel@wdc.com>

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 <anup.patel@wdc.com>
---
 include/sbi_utils/gpio/gpio.h |  99 +++++++++++++++++++++++++++++
 lib/utils/gpio/gpio.c         | 116 ++++++++++++++++++++++++++++++++++
 lib/utils/gpio/objects.mk     |  10 +++
 3 files changed, 225 insertions(+)
 create mode 100644 include/sbi_utils/gpio/gpio.h
 create mode 100644 lib/utils/gpio/gpio.c
 create mode 100644 lib/utils/gpio/objects.mk

Comments

Anup Patel July 17, 2021, 8:47 a.m. UTC | #1
On Tue, Jul 13, 2021 at 8:54 AM Green Wan <green.wan@sifive.com> wrote:
>
> From: Anup Patel <anup.patel@wdc.com>
>
> 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 <anup.patel@wdc.com>

Atish's reviewed-by is missing which I have added at time of merging

Applied this patch to the riscv/opensbi repo

Thanks,
Anup

> ---
>  include/sbi_utils/gpio/gpio.h |  99 +++++++++++++++++++++++++++++
>  lib/utils/gpio/gpio.c         | 116 ++++++++++++++++++++++++++++++++++
>  lib/utils/gpio/objects.mk     |  10 +++
>  3 files changed, 225 insertions(+)
>  create mode 100644 include/sbi_utils/gpio/gpio.h
>  create mode 100644 lib/utils/gpio/gpio.c
>  create mode 100644 lib/utils/gpio/objects.mk
>
> 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 <anup.patel@wdc.com>
> + */
> +
> +#ifndef __GPIO_H__
> +#define __GPIO_H__
> +
> +#include <sbi/sbi_types.h>
> +
> +#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 <anup.patel@wdc.com>
> + */
> +
> +#include <sbi/sbi_error.h>
> +#include <sbi_utils/gpio/gpio.h>
> +
> +#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 <anup.patel@wdc.com>
> +#
> +
> +libsbiutils-objs-y += gpio/gpio.o
> --
> 2.17.1
>
>
> --
> opensbi mailing list
> opensbi@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi
diff mbox series

Patch

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 <anup.patel@wdc.com>
+ */
+
+#ifndef __GPIO_H__
+#define __GPIO_H__
+
+#include <sbi/sbi_types.h>
+
+#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 <anup.patel@wdc.com>
+ */
+
+#include <sbi/sbi_error.h>
+#include <sbi_utils/gpio/gpio.h>
+
+#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 <anup.patel@wdc.com>
+#
+
+libsbiutils-objs-y += gpio/gpio.o