diff --git a/bindings/cxx/chip.cpp b/bindings/cxx/chip.cpp
index 527fb34..0886717 100644
--- a/bindings/cxx/chip.cpp
+++ b/bindings/cxx/chip.cpp
@@ -13,7 +13,7 @@ namespace {
 
 void chip_deleter(::gpiod_chip* chip)
 {
-	::gpiod_chip_close(chip);
+	::gpiod_chip_unref(chip);
 }
 
 } /* namespace */
diff --git a/bindings/python/gpiodmodule.c b/bindings/python/gpiodmodule.c
index ac0fd83..e54c3ad 100644
--- a/bindings/python/gpiodmodule.c
+++ b/bindings/python/gpiodmodule.c
@@ -1953,7 +1953,7 @@ static int gpiod_Chip_init(gpiod_ChipObject *self,
 static void gpiod_Chip_dealloc(gpiod_ChipObject *self)
 {
 	if (self->chip)
-		gpiod_chip_close(self->chip);
+		gpiod_chip_unref(self->chip);
 
 	PyObject_Del(self);
 }
@@ -1981,7 +1981,7 @@ static PyObject *gpiod_Chip_close(gpiod_ChipObject *self,
 	if (gpiod_ChipIsClosed(self))
 		return NULL;
 
-	gpiod_chip_close(self->chip);
+	gpiod_chip_unref(self->chip);
 	self->chip = NULL;
 
 	Py_RETURN_NONE;
diff --git a/include/gpiod.h b/include/gpiod.h
index 6ed9c6c..71abb2a 100644
--- a/include/gpiod.h
+++ b/include/gpiod.h
@@ -81,10 +81,18 @@ bool gpiod_is_gpiochip_device(const char *path) GPIOD_API;
 struct gpiod_chip *gpiod_chip_open(const char *path) GPIOD_API;
 
 /**
- * @brief Close a GPIO chip handle and release all allocated resources.
+ * @brief Increase the refcount on this GPIO object.
  * @param chip The GPIO chip object.
+ * @return Passed reference to the GPIO chip.
  */
-void gpiod_chip_close(struct gpiod_chip *chip) GPIOD_API;
+struct gpiod_chip *gpiod_chip_ref(struct gpiod_chip *chip) GPIOD_API;
+
+/**
+ * @brief Decrease the refcount on this GPIO object. If the refcount reaches 0,
+ *        close the chip device and free all associated resources.
+ * @param chip The GPIO chip object.
+ */
+void gpiod_chip_unref(struct gpiod_chip *chip) GPIOD_API;
 
 /**
  * @brief Get the GPIO chip name as represented in the kernel.
diff --git a/lib/core.c b/lib/core.c
index 077ea3e..bab438f 100644
--- a/lib/core.c
+++ b/lib/core.c
@@ -64,6 +64,8 @@ struct gpiod_line {
 };
 
 struct gpiod_chip {
+	int refcount;
+
 	struct gpiod_line **lines;
 	unsigned int num_lines;
 
@@ -297,6 +299,7 @@ struct gpiod_chip *gpiod_chip_open(const char *path)
 
 	chip->fd = fd;
 	chip->num_lines = info.lines;
+	chip->refcount = 1;
 
 	/*
 	 * GPIO device must have a name - don't bother checking this field. In
@@ -324,11 +327,21 @@ err_close_fd:
 	return NULL;
 }
 
-void gpiod_chip_close(struct gpiod_chip *chip)
+struct gpiod_chip *gpiod_chip_ref(struct gpiod_chip *chip)
+{
+	chip->refcount++;
+	return chip;
+}
+
+void gpiod_chip_unref(struct gpiod_chip *chip)
 {
 	struct gpiod_line *line;
 	unsigned int i;
 
+	chip->refcount--;
+	if (chip->refcount > 0)
+		return;
+
 	if (chip->lines) {
 		for (i = 0; i < chip->num_lines; i++) {
 			line = chip->lines[i];
diff --git a/tests/gpiod-test.h b/tests/gpiod-test.h
index 2688d3c..a093f83 100644
--- a/tests/gpiod-test.h
+++ b/tests/gpiod-test.h
@@ -22,7 +22,7 @@
 typedef struct gpiod_chip gpiod_chip_struct;
 typedef struct gpiod_line_bulk gpiod_line_bulk_struct;
 
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(gpiod_chip_struct, gpiod_chip_close);
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(gpiod_chip_struct, gpiod_chip_unref);
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(gpiod_line_bulk_struct, gpiod_line_bulk_free);
 
 /* These are private definitions and should not be used directly. */
diff --git a/tools/gpiodetect.c b/tools/gpiodetect.c
index 7a2015e..9f4c28c 100644
--- a/tools/gpiodetect.c
+++ b/tools/gpiodetect.c
@@ -80,7 +80,7 @@ int main(int argc, char **argv)
 		       gpiod_chip_label(chip),
 		       gpiod_chip_num_lines(chip));
 
-		gpiod_chip_close(chip);
+		gpiod_chip_unref(chip);
 		free(entries[i]);
 	}
 
diff --git a/tools/gpiofind.c b/tools/gpiofind.c
index 0fc07d9..83af76b 100644
--- a/tools/gpiofind.c
+++ b/tools/gpiofind.c
@@ -77,7 +77,7 @@ int main(int argc, char **argv)
 		if (offset >= 0) {
 			printf("%s %u\n",
 			       gpiod_chip_name(chip), offset);
-			gpiod_chip_close(chip);
+			gpiod_chip_unref(chip);
 			return EXIT_SUCCESS;
 		}
 	}
diff --git a/tools/gpioget.c b/tools/gpioget.c
index 527dc22..ceeec56 100644
--- a/tools/gpioget.c
+++ b/tools/gpioget.c
@@ -123,7 +123,7 @@ int main(int argc, char **argv)
 	printf("\n");
 
 	gpiod_line_release_bulk(lines);
-	gpiod_chip_close(chip);
+	gpiod_chip_unref(chip);
 	gpiod_line_bulk_free(lines);
 	free(values);
 	free(offsets);
diff --git a/tools/gpioinfo.c b/tools/gpioinfo.c
index 84588bc..eba8c72 100644
--- a/tools/gpioinfo.c
+++ b/tools/gpioinfo.c
@@ -230,7 +230,7 @@ int main(int argc, char **argv)
 
 			list_lines(chip);
 
-			gpiod_chip_close(chip);
+			gpiod_chip_unref(chip);
 		}
 	} else {
 		for (i = 0; i < argc; i++) {
@@ -240,7 +240,7 @@ int main(int argc, char **argv)
 
 			list_lines(chip);
 
-			gpiod_chip_close(chip);
+			gpiod_chip_unref(chip);
 		}
 	}
 
diff --git a/tools/gpiomon.c b/tools/gpiomon.c
index 8bf2c70..dda9f6f 100644
--- a/tools/gpiomon.c
+++ b/tools/gpiomon.c
@@ -306,7 +306,7 @@ done:
 	gpiod_line_release_bulk(lines);
 	gpiod_line_bulk_free(lines);
 	gpiod_line_bulk_free(evlines);
-	gpiod_chip_close(chip);
+	gpiod_chip_unref(chip);
 
 	return EXIT_SUCCESS;
 }
diff --git a/tools/gpioset.c b/tools/gpioset.c
index 7e9d88f..a088ec6 100644
--- a/tools/gpioset.c
+++ b/tools/gpioset.c
@@ -305,7 +305,7 @@ int main(int argc, char **argv)
 	mode->callback(&cbdata);
 
 	gpiod_line_release_bulk(lines);
-	gpiod_chip_close(chip);
+	gpiod_chip_unref(chip);
 	gpiod_line_bulk_free(lines);
 	free(offsets);
 	free(values);
