diff --git a/tools/gpiodetect.c b/tools/gpiodetect.c
index 8f6e8b3..2fada05 100644
--- a/tools/gpiodetect.c
+++ b/tools/gpiodetect.c
@@ -67,7 +67,7 @@ int main(int argc, char **argv)
 		die_perror("unable to scan /dev");
 
 	for (i = 0; i < num_chips; i++) {
-		chip = chip_open_by_name(entries[i]->d_name);
+		chip = chip_open(chip_path_from_name(entries[i]->d_name));
 		if (!chip)
 			die_perror("unable to open %s", entries[i]->d_name);
 
diff --git a/tools/gpiofind.c b/tools/gpiofind.c
index 36eba86..17e1702 100644
--- a/tools/gpiofind.c
+++ b/tools/gpiofind.c
@@ -67,7 +67,7 @@ int main(int argc, char **argv)
 		die_perror("unable to scan /dev");
 
 	for (i = 0; i < num_chips; i++) {
-		chip = chip_open_by_name(entries[i]->d_name);
+		chip = chip_open(chip_path_from_name(entries[i]->d_name));
 		if (!chip) {
 			if (errno == EACCES)
 				continue;
diff --git a/tools/gpioget.c b/tools/gpioget.c
index 2cf5eae..f4c5d46 100644
--- a/tools/gpioget.c
+++ b/tools/gpioget.c
@@ -46,11 +46,10 @@ int main(int argc, char **argv)
 	struct gpiod_request_config *req_cfg;
 	struct gpiod_line_request *request;
 	struct gpiod_line_config *line_cfg;
-	struct gpiod_chip *chip;
 	bool active_low = false;
 	unsigned int *offsets, *values;
 	size_t i, num_lines;
-	char *device, *end;
+	char *device, *end, *path;
 
 	for (;;) {
 		optc = getopt_long(argc, argv, shortopts, longopts, &opti);
@@ -103,8 +102,8 @@ int main(int argc, char **argv)
 			die("invalid GPIO offset: %s", argv[i + 1]);
 	}
 
-	chip = chip_open_lookup(device);
-	if (!chip)
+	path = chip_path_lookup(device);
+	if (!path)
 		die_perror("unable to open %s", device);
 
 	line_cfg = gpiod_line_config_new();
@@ -126,7 +125,7 @@ int main(int argc, char **argv)
 	gpiod_request_config_set_consumer(req_cfg, "gpioget");
 	gpiod_request_config_set_offsets(req_cfg, num_lines, offsets);
 
-	request = gpiod_chip_request_lines(chip, req_cfg, line_cfg);
+	request = gpiod_request_lines(path, req_cfg, line_cfg);
 	if (!request)
 		die_perror("unable to request lines");
 
@@ -144,7 +143,7 @@ int main(int argc, char **argv)
 	gpiod_line_request_release(request);
 	gpiod_request_config_free(req_cfg);
 	gpiod_line_config_free(line_cfg);
-	gpiod_chip_close(chip);
+	free(path);
 	free(offsets);
 	free(values);
 
diff --git a/tools/gpioinfo.c b/tools/gpioinfo.c
index fbe2a13..f0f9926 100644
--- a/tools/gpioinfo.c
+++ b/tools/gpioinfo.c
@@ -227,7 +227,7 @@ int main(int argc, char **argv)
 			die_perror("unable to scan /dev");
 
 		for (i = 0; i < num_chips; i++) {
-			chip = chip_open_by_name(entries[i]->d_name);
+			chip = chip_open(chip_path_from_name(entries[i]->d_name));
 			if (!chip)
 				die_perror("unable to open %s",
 					   entries[i]->d_name);
@@ -240,7 +240,7 @@ int main(int argc, char **argv)
 		free(entries);
 	} else {
 		for (i = 0; i < argc; i++) {
-			chip = chip_open_lookup(argv[i]);
+			chip = chip_open(chip_path_lookup(argv[i]));
 			if (!chip)
 				die_perror("looking up chip %s", argv[i]);
 
diff --git a/tools/gpiomon.c b/tools/gpiomon.c
index f6a0dba..e461458 100644
--- a/tools/gpiomon.c
+++ b/tools/gpiomon.c
@@ -164,9 +164,8 @@ int main(int argc, char **argv)
 	struct gpiod_line_config *line_cfg;
 	unsigned int offsets[64], offset;
 	struct gpiod_edge_event *event;
-	struct gpiod_chip *chip;
 	struct mon_ctx ctx;
-	char *end;
+	char *end, *path;
 
 	/*
 	 * FIXME: use signalfd once the API has been converted to using a single file
@@ -250,8 +249,8 @@ int main(int argc, char **argv)
 		num_lines++;
 	}
 
-	chip = chip_open_lookup(argv[0]);
-	if (!chip)
+	path = chip_path_lookup(argv[0]);
+	if (!path)
 		die_perror("unable to open %s", argv[0]);
 
 	line_cfg = gpiod_line_config_new();
@@ -271,7 +270,7 @@ int main(int argc, char **argv)
 	gpiod_request_config_set_consumer(req_cfg, "gpiomon");
 	gpiod_request_config_set_offsets(req_cfg, num_lines, offsets);
 
-	request = gpiod_chip_request_lines(chip, req_cfg, line_cfg);
+	request = gpiod_request_lines(path, req_cfg, line_cfg);
 	if (!request)
 		die_perror("unable to request lines");
 
@@ -314,7 +313,7 @@ done:
 	gpiod_line_request_release(request);
 	gpiod_request_config_free(req_cfg);
 	gpiod_line_config_free(line_cfg);
-	gpiod_chip_close(chip);
+	free(path);
 
 	return EXIT_SUCCESS;
 }
diff --git a/tools/gpioset.c b/tools/gpioset.c
index 1c11470..7497eab 100644
--- a/tools/gpioset.c
+++ b/tools/gpioset.c
@@ -195,11 +195,10 @@ int main(int argc, char **argv)
 	struct gpiod_line_request *request;
 	struct gpiod_line_config *line_cfg;
 	struct callback_data cbdata;
-	struct gpiod_chip *chip;
 	bool active_low = false;
 	unsigned int *offsets, *values;
 	size_t i, num_lines;
-	char *device, *end;
+	char *device, *end, *path;
 
 	memset(&cbdata, 0, sizeof(cbdata));
 
@@ -288,8 +287,8 @@ int main(int argc, char **argv)
 			die("invalid offset: %s", argv[i + 1]);
 	}
 
-	chip = chip_open_lookup(device);
-	if (!chip)
+	path = chip_path_lookup(device);
+	if (!path)
 		die_perror("unable to open %s", device);
 
 	line_cfg = gpiod_line_config_new();
@@ -314,7 +313,7 @@ int main(int argc, char **argv)
 	gpiod_request_config_set_consumer(req_cfg, "gpioset");
 	gpiod_request_config_set_offsets(req_cfg, num_lines, offsets);
 
-	request = gpiod_chip_request_lines(chip, req_cfg, line_cfg);
+	request = gpiod_request_lines(path, req_cfg, line_cfg);
 	if (!request)
 		die_perror("unable to request lines");
 
@@ -324,7 +323,7 @@ int main(int argc, char **argv)
 	gpiod_line_request_release(request);
 	gpiod_request_config_free(req_cfg);
 	gpiod_line_config_free(line_cfg);
-	gpiod_chip_close(chip);
+	free(path);
 	free(offsets);
 
 	return EXIT_SUCCESS;
diff --git a/tools/tools-common.c b/tools/tools-common.c
index f5fd50c..8d4ca12 100644
--- a/tools/tools-common.c
+++ b/tools/tools-common.c
@@ -114,36 +114,24 @@ int chip_dir_filter(const struct dirent *entry)
 	return !!is_chip;
 }
 
-struct gpiod_chip *chip_open_by_name(const char *name)
+char *chip_path_from_name(const char *name)
 {
-	struct gpiod_chip *chip;
 	char *path;
-	int ret;
 
-	ret = asprintf(&path, "/dev/%s", name);
-	if (ret < 0)
+	if (asprintf(&path, "/dev/%s", name) < 0)
 		return NULL;
 
-	chip = gpiod_chip_open(path);
-	free(path);
-
-	return chip;
+	return path;
 }
 
-static struct gpiod_chip *chip_open_by_number(unsigned int num)
+static char *chip_path_from_number(unsigned int num)
 {
-	struct gpiod_chip *chip;
 	char *path;
-	int ret;
 
-	ret = asprintf(&path, "/dev/gpiochip%u", num);
-	if (!ret)
+	if (asprintf(&path, "/dev/gpiochip%u", num) < 0)
 		return NULL;
 
-	chip = gpiod_chip_open(path);
-	free(path);
-
-	return chip;
+	return path;
 }
 
 static bool isuint(const char *str)
@@ -154,18 +142,18 @@ static bool isuint(const char *str)
 	return *str == '\0';
 }
 
-struct gpiod_chip *chip_open_lookup(const char *device)
+char *chip_path_lookup(const char *device)
 {
-	struct gpiod_chip *chip;
-
-	if (isuint(device)) {
-		chip = chip_open_by_number(strtoul(device, NULL, 10));
-	} else {
-		if (strncmp(device, "/dev/", 5))
-			chip = chip_open_by_name(device);
-		else
-			chip = gpiod_chip_open(device);
-	}
-
-	return chip;
+	if (isuint(device))
+		return chip_path_from_number(strtoul(device, NULL, 10));
+	if (strncmp(device, "/dev/", 5))
+		return chip_path_from_name(device);
+	return strdup(device);
+}
+
+struct gpiod_chip *chip_open(const char *path)
+{
+	if (path == NULL)
+		return NULL;
+	return gpiod_chip_open(path);
 }
diff --git a/tools/tools-common.h b/tools/tools-common.h
index f059440..d0b3a83 100644
--- a/tools/tools-common.h
+++ b/tools/tools-common.h
@@ -29,7 +29,8 @@ int parse_bias(const char *option);
 void print_bias_help(void);
 int make_signalfd(void);
 int chip_dir_filter(const struct dirent *entry);
-struct gpiod_chip *chip_open_by_name(const char *name);
-struct gpiod_chip *chip_open_lookup(const char *device);
+struct gpiod_chip *chip_open(const char *path);
+char *chip_path_from_name(const char *name);
+char *chip_path_lookup(const char *device);
 
 #endif /* __GPIOD_TOOLS_COMMON_H__ */
