drivers/gpio/gpio-ws16c48.c
Source file repositories/reference/linux-study-clean/drivers/gpio/gpio-ws16c48.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/gpio/gpio-ws16c48.c- Extension
.c- Size
- 10300 bytes
- Lines
- 328
- 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/bitfield.hlinux/bits.hlinux/device.hlinux/err.hlinux/gpio/regmap.hlinux/irq.hlinux/isa.hlinux/kernel.hlinux/module.hlinux/moduleparam.hlinux/spinlock.hlinux/regmap.hlinux/types.h
Detected Declarations
struct ws16c48_gpiofunction ws16c48_handle_pre_irqfunction ws16c48_handle_post_irqfunction ws16c48_handle_mask_syncfunction ws16c48_set_type_configfunction ws16c48_irq_init_hwfunction ws16c48_probe
Annotated Snippet
struct ws16c48_gpio {
struct regmap *map;
raw_spinlock_t lock;
u8 irq_mask[WS16C48_NUM_IRQS / WS16C48_NGPIO_PER_REG];
};
static int ws16c48_handle_pre_irq(void *const irq_drv_data) __acquires(&ws16c48gpio->lock)
{
struct ws16c48_gpio *const ws16c48gpio = irq_drv_data;
/* Lock to prevent Page/Lock register change while we handle IRQ */
raw_spin_lock(&ws16c48gpio->lock);
return 0;
}
static int ws16c48_handle_post_irq(void *const irq_drv_data) __releases(&ws16c48gpio->lock)
{
struct ws16c48_gpio *const ws16c48gpio = irq_drv_data;
raw_spin_unlock(&ws16c48gpio->lock);
return 0;
}
static int ws16c48_handle_mask_sync(const int index, const unsigned int mask_buf_def,
const unsigned int mask_buf, void *const irq_drv_data)
{
struct ws16c48_gpio *const ws16c48gpio = irq_drv_data;
unsigned long flags;
int ret = 0;
raw_spin_lock_irqsave(&ws16c48gpio->lock, flags);
/* exit early if no change since the last mask sync */
if (mask_buf == ws16c48gpio->irq_mask[index])
goto exit_unlock;
ws16c48gpio->irq_mask[index] = mask_buf;
ret = regmap_write(ws16c48gpio->map, WS16C48_PAGE_LOCK, ENAB_PAGE);
if (ret)
goto exit_unlock;
/* Update ENAB register (inverted mask) */
ret = regmap_write(ws16c48gpio->map, WS16C48_ENAB + index, ~mask_buf);
if (ret)
goto exit_unlock;
ret = regmap_write(ws16c48gpio->map, WS16C48_PAGE_LOCK, INT_ID_PAGE);
if (ret)
goto exit_unlock;
exit_unlock:
raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags);
return ret;
}
static int ws16c48_set_type_config(unsigned int **const buf, const unsigned int type,
const struct regmap_irq *const irq_data, const int idx,
void *const irq_drv_data)
{
struct ws16c48_gpio *const ws16c48gpio = irq_drv_data;
unsigned int polarity;
unsigned long flags;
int ret;
switch (type) {
case IRQ_TYPE_EDGE_RISING:
polarity = irq_data->mask;
break;
case IRQ_TYPE_EDGE_FALLING:
polarity = 0;
break;
default:
return -EINVAL;
}
raw_spin_lock_irqsave(&ws16c48gpio->lock, flags);
ret = regmap_write(ws16c48gpio->map, WS16C48_PAGE_LOCK, POL_PAGE);
if (ret)
goto exit_unlock;
/* Set interrupt polarity */
ret = regmap_update_bits(ws16c48gpio->map, WS16C48_POL + idx, irq_data->mask, polarity);
if (ret)
goto exit_unlock;
ret = regmap_write(ws16c48gpio->map, WS16C48_PAGE_LOCK, INT_ID_PAGE);
Annotation
- Immediate include surface: `linux/bitfield.h`, `linux/bits.h`, `linux/device.h`, `linux/err.h`, `linux/gpio/regmap.h`, `linux/irq.h`, `linux/isa.h`, `linux/kernel.h`.
- Detected declarations: `struct ws16c48_gpio`, `function ws16c48_handle_pre_irq`, `function ws16c48_handle_post_irq`, `function ws16c48_handle_mask_sync`, `function ws16c48_set_type_config`, `function ws16c48_irq_init_hw`, `function ws16c48_probe`.
- 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.