18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci#include <linux/gpio/consumer.h>
38c2ecf20Sopenharmony_ci#include <linux/gpio/driver.h>
48c2ecf20Sopenharmony_ci
58c2ecf20Sopenharmony_ci#include <linux/gpio.h>
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci#include "gpiolib.h"
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_civoid gpio_free(unsigned gpio)
108c2ecf20Sopenharmony_ci{
118c2ecf20Sopenharmony_ci	gpiod_free(gpio_to_desc(gpio));
128c2ecf20Sopenharmony_ci}
138c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(gpio_free);
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_ci/**
168c2ecf20Sopenharmony_ci * gpio_request_one - request a single GPIO with initial configuration
178c2ecf20Sopenharmony_ci * @gpio:	the GPIO number
188c2ecf20Sopenharmony_ci * @flags:	GPIO configuration as specified by GPIOF_*
198c2ecf20Sopenharmony_ci * @label:	a literal description string of this GPIO
208c2ecf20Sopenharmony_ci */
218c2ecf20Sopenharmony_ciint gpio_request_one(unsigned gpio, unsigned long flags, const char *label)
228c2ecf20Sopenharmony_ci{
238c2ecf20Sopenharmony_ci	struct gpio_desc *desc;
248c2ecf20Sopenharmony_ci	int err;
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci	desc = gpio_to_desc(gpio);
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ci	/* Compatibility: assume unavailable "valid" GPIOs will appear later */
298c2ecf20Sopenharmony_ci	if (!desc && gpio_is_valid(gpio))
308c2ecf20Sopenharmony_ci		return -EPROBE_DEFER;
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ci	err = gpiod_request(desc, label);
338c2ecf20Sopenharmony_ci	if (err)
348c2ecf20Sopenharmony_ci		return err;
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci	if (flags & GPIOF_OPEN_DRAIN)
378c2ecf20Sopenharmony_ci		set_bit(FLAG_OPEN_DRAIN, &desc->flags);
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_ci	if (flags & GPIOF_OPEN_SOURCE)
408c2ecf20Sopenharmony_ci		set_bit(FLAG_OPEN_SOURCE, &desc->flags);
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci	if (flags & GPIOF_ACTIVE_LOW)
438c2ecf20Sopenharmony_ci		set_bit(FLAG_ACTIVE_LOW, &desc->flags);
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci	if (flags & GPIOF_DIR_IN)
468c2ecf20Sopenharmony_ci		err = gpiod_direction_input(desc);
478c2ecf20Sopenharmony_ci	else
488c2ecf20Sopenharmony_ci		err = gpiod_direction_output_raw(desc,
498c2ecf20Sopenharmony_ci				(flags & GPIOF_INIT_HIGH) ? 1 : 0);
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci	if (err)
528c2ecf20Sopenharmony_ci		goto free_gpio;
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_ci	if (flags & GPIOF_EXPORT) {
558c2ecf20Sopenharmony_ci		err = gpiod_export(desc, flags & GPIOF_EXPORT_CHANGEABLE);
568c2ecf20Sopenharmony_ci		if (err)
578c2ecf20Sopenharmony_ci			goto free_gpio;
588c2ecf20Sopenharmony_ci	}
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_ci	return 0;
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci free_gpio:
638c2ecf20Sopenharmony_ci	gpiod_free(desc);
648c2ecf20Sopenharmony_ci	return err;
658c2ecf20Sopenharmony_ci}
668c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(gpio_request_one);
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_ciint gpio_request(unsigned gpio, const char *label)
698c2ecf20Sopenharmony_ci{
708c2ecf20Sopenharmony_ci	struct gpio_desc *desc = gpio_to_desc(gpio);
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_ci	/* Compatibility: assume unavailable "valid" GPIOs will appear later */
738c2ecf20Sopenharmony_ci	if (!desc && gpio_is_valid(gpio))
748c2ecf20Sopenharmony_ci		return -EPROBE_DEFER;
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_ci	return gpiod_request(desc, label);
778c2ecf20Sopenharmony_ci}
788c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(gpio_request);
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_ci/**
818c2ecf20Sopenharmony_ci * gpio_request_array - request multiple GPIOs in a single call
828c2ecf20Sopenharmony_ci * @array:	array of the 'struct gpio'
838c2ecf20Sopenharmony_ci * @num:	how many GPIOs in the array
848c2ecf20Sopenharmony_ci */
858c2ecf20Sopenharmony_ciint gpio_request_array(const struct gpio *array, size_t num)
868c2ecf20Sopenharmony_ci{
878c2ecf20Sopenharmony_ci	int i, err;
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_ci	for (i = 0; i < num; i++, array++) {
908c2ecf20Sopenharmony_ci		err = gpio_request_one(array->gpio, array->flags, array->label);
918c2ecf20Sopenharmony_ci		if (err)
928c2ecf20Sopenharmony_ci			goto err_free;
938c2ecf20Sopenharmony_ci	}
948c2ecf20Sopenharmony_ci	return 0;
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_cierr_free:
978c2ecf20Sopenharmony_ci	while (i--)
988c2ecf20Sopenharmony_ci		gpio_free((--array)->gpio);
998c2ecf20Sopenharmony_ci	return err;
1008c2ecf20Sopenharmony_ci}
1018c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(gpio_request_array);
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_ci/**
1048c2ecf20Sopenharmony_ci * gpio_free_array - release multiple GPIOs in a single call
1058c2ecf20Sopenharmony_ci * @array:	array of the 'struct gpio'
1068c2ecf20Sopenharmony_ci * @num:	how many GPIOs in the array
1078c2ecf20Sopenharmony_ci */
1088c2ecf20Sopenharmony_civoid gpio_free_array(const struct gpio *array, size_t num)
1098c2ecf20Sopenharmony_ci{
1108c2ecf20Sopenharmony_ci	while (num--)
1118c2ecf20Sopenharmony_ci		gpio_free((array++)->gpio);
1128c2ecf20Sopenharmony_ci}
1138c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(gpio_free_array);
114