drivers/gpio/gpio-latch.c
Source file repositories/reference/linux-study-clean/drivers/gpio/gpio-latch.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/gpio/gpio-latch.c- Extension
.c- Size
- 6665 bytes
- Lines
- 222
- Domain
- Driver Families
- Bucket
- drivers/gpio
- Inferred role
- Driver Families: implementation source
- Status
- source 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.
- 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.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/cleanup.hlinux/err.hlinux/gpio/consumer.hlinux/gpio/driver.hlinux/module.hlinux/mod_devicetable.hlinux/platform_device.hlinux/property.hlinux/delay.h
Detected Declarations
struct gpio_latch_privfunction gpio_latch_get_directionfunction gpio_latch_set_unlockedfunction gpio_latch_setfunction gpio_latch_set_can_sleepfunction gpio_latch_can_sleepfunction usleep_range
Annotated Snippet
struct gpio_latch_priv {
struct gpio_chip gc;
struct gpio_descs *clk_gpios;
struct gpio_descs *latched_gpios;
int n_latched_gpios;
unsigned int setup_duration_ns;
unsigned int clock_duration_ns;
unsigned long *shadow;
/*
* Depending on whether any of the underlying GPIOs may sleep we either
* use a mutex or a spinlock to protect our shadow map.
*/
union {
struct mutex mutex; /* protects @shadow */
spinlock_t spinlock; /* protects @shadow */
};
};
static int gpio_latch_get_direction(struct gpio_chip *gc, unsigned int offset)
{
return GPIO_LINE_DIRECTION_OUT;
}
static int gpio_latch_set_unlocked(struct gpio_latch_priv *priv,
int (*set)(struct gpio_desc *desc, int value),
unsigned int offset, bool val)
{
int latch = offset / priv->n_latched_gpios, i, ret;
assign_bit(offset, priv->shadow, val);
for (i = 0; i < priv->n_latched_gpios; i++) {
ret = set(priv->latched_gpios->desc[i],
test_bit(latch * priv->n_latched_gpios + i,
priv->shadow));
if (ret)
return ret;
}
ndelay(priv->setup_duration_ns);
set(priv->clk_gpios->desc[latch], 1);
ndelay(priv->clock_duration_ns);
set(priv->clk_gpios->desc[latch], 0);
return 0;
}
static int gpio_latch_set(struct gpio_chip *gc, unsigned int offset, int val)
{
struct gpio_latch_priv *priv = gpiochip_get_data(gc);
guard(spinlock_irqsave)(&priv->spinlock);
return gpio_latch_set_unlocked(priv, gpiod_set_value, offset, val);
}
static int gpio_latch_set_can_sleep(struct gpio_chip *gc, unsigned int offset, int val)
{
struct gpio_latch_priv *priv = gpiochip_get_data(gc);
guard(mutex)(&priv->mutex);
return gpio_latch_set_unlocked(priv, gpiod_set_value_cansleep, offset, val);
}
static bool gpio_latch_can_sleep(struct gpio_latch_priv *priv, unsigned int n_latches)
{
int i;
for (i = 0; i < n_latches; i++)
if (gpiod_cansleep(priv->clk_gpios->desc[i]))
return true;
for (i = 0; i < priv->n_latched_gpios; i++)
if (gpiod_cansleep(priv->latched_gpios->desc[i]))
return true;
return false;
}
/*
* Some value which is still acceptable to delay in atomic context.
* If we need to go higher we might have to switch to usleep_range(),
* but that cannot ne used in atomic context and the driver would have
* to be adjusted to support that.
*/
#define DURATION_NS_MAX 5000
static int gpio_latch_probe(struct platform_device *pdev)
{
Annotation
- Immediate include surface: `linux/cleanup.h`, `linux/err.h`, `linux/gpio/consumer.h`, `linux/gpio/driver.h`, `linux/module.h`, `linux/mod_devicetable.h`, `linux/platform_device.h`, `linux/property.h`.
- Detected declarations: `struct gpio_latch_priv`, `function gpio_latch_get_direction`, `function gpio_latch_set_unlocked`, `function gpio_latch_set`, `function gpio_latch_set_can_sleep`, `function gpio_latch_can_sleep`, `function usleep_range`.
- Atlas domain: Driver Families / drivers/gpio.
- Implementation status: source implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.