From 36b8effe4a07bbf476deca6c8769529c69078f08 Mon Sep 17 00:00:00 2001
From: Anup Patel <anup.patel@wdc.com>
Date: Tue, 13 Jul 2021 11:23:42 +0800
Subject: 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 <anup.patel@wdc.com>
Reviewed-by: Atish Patra <atish.patra@wdc.com>
---
 lib/utils/gpio/gpio.c     | 116 ++++++++++++++++++++++++++++++++++++++++++++++
 lib/utils/gpio/objects.mk |  10 ++++
 2 files changed, 126 insertions(+)
 create mode 100644 lib/utils/gpio/gpio.c
 create mode 100644 lib/utils/gpio/objects.mk

(limited to 'lib/utils')

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
-- 
cgit v1.2.3