drivers/gpio/gpiolib-shared.c

Source file repositories/reference/linux-study-clean/drivers/gpio/gpiolib-shared.c

File Facts

System
Linux kernel
Corpus path
drivers/gpio/gpiolib-shared.c
Extension
.c
Size
20288 bytes
Lines
803
Domain
Driver Families
Bucket
drivers/gpio
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct gpio_shared_ref {
	struct list_head list;
	/* Firmware node associated with this GPIO's consumer. */
	struct fwnode_handle *fwnode;
	/* GPIO flags this consumer uses for the request. */
	enum gpiod_flags flags;
	char *con_id;
	int dev_id;
	/* Protects the auxiliary device struct and the lookup table. */
	struct mutex lock;
	struct lock_class_key lock_key;
	struct auxiliary_device adev;
	struct gpiod_lookup_table *lookup;
	bool is_reset_gpio;
};

/* Represents a single GPIO pin. */
struct gpio_shared_entry {
	struct list_head list;
	/* Firmware node associated with the GPIO controller. */
	struct fwnode_handle *fwnode;
	/* Hardware offset of the GPIO within its chip. */
	unsigned int offset;
	/* Index in the property value array. */
	size_t index;
	/* Synchronizes the modification of shared_desc and offset. */
	struct mutex lock;
	struct gpio_shared_desc *shared_desc;
	struct kref ref;
	struct list_head refs;
};

static LIST_HEAD(gpio_shared_list);
static DEFINE_IDA(gpio_shared_ida);

#if IS_ENABLED(CONFIG_OF)
static struct gpio_shared_entry *
gpio_shared_find_entry(struct fwnode_handle *controller_node,
		       unsigned int offset)
{
	struct gpio_shared_entry *entry;

	list_for_each_entry(entry, &gpio_shared_list, list) {
		if (entry->fwnode == controller_node && entry->offset == offset)
			return entry;
	}

	return NULL;
}

static struct gpio_shared_ref *gpio_shared_make_ref(struct fwnode_handle *fwnode,
						    const char *con_id,
						    enum gpiod_flags flags)
{
	char *con_id_cpy __free(kfree) = NULL;

	struct gpio_shared_ref *ref __free(kfree) = kzalloc_obj(*ref);
	if (!ref)
		return NULL;

	if (con_id) {
		con_id_cpy = kstrdup(con_id, GFP_KERNEL);
		if (!con_id_cpy)
			return NULL;
	}

	ref->dev_id = ida_alloc(&gpio_shared_ida, GFP_KERNEL);
	if (ref->dev_id < 0)
		return NULL;

	ref->flags = flags;
	ref->con_id = no_free_ptr(con_id_cpy);
	ref->fwnode = fwnode;
	lockdep_register_key(&ref->lock_key);
	mutex_init_with_key(&ref->lock, &ref->lock_key);

	return no_free_ptr(ref);
}

static int gpio_shared_setup_reset_proxy(struct gpio_shared_entry *entry,
					 enum gpiod_flags flags)
{
	struct gpio_shared_ref *ref;

	list_for_each_entry(ref, &entry->refs, list) {
		if (ref->is_reset_gpio)
			/* Already set-up. */
			return 0;
	}

Annotation

Implementation Notes