drivers/misc/mchp_pci1xxxx/mchp_pci1xxxx_gpio.c
Source file repositories/reference/linux-study-clean/drivers/misc/mchp_pci1xxxx/mchp_pci1xxxx_gpio.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/misc/mchp_pci1xxxx/mchp_pci1xxxx_gpio.c- Extension
.c- Size
- 15824 bytes
- Lines
- 534
- Domain
- Driver Families
- Bucket
- drivers/misc
- 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.
- Touches IRQ or DMA behavior; this matters for the representative real-device path.
- 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/module.hlinux/spinlock.hlinux/gpio/driver.hlinux/bio.hlinux/mutex.hlinux/pci.hlinux/kthread.hlinux/interrupt.hmchp_pci1xxxx_gp.h
Detected Declarations
struct pci1xxxx_gpiofunction pci1xxxx_gpio_get_device_revisionfunction pci1xxxx_gpio_get_directionfunction pci1xxx_assign_bitfunction pci1xxxx_gpio_direction_inputfunction pci1xxxx_gpio_getfunction pci1xxxx_gpio_direction_outputfunction pci1xxxx_gpio_setfunction pci1xxxx_gpio_set_configfunction pci1xxxx_gpio_irq_ackfunction pci1xxxx_gpio_irq_set_maskfunction pci1xxxx_gpio_irq_maskfunction pci1xxxx_gpio_irq_unmaskfunction pci1xxxx_gpio_set_typefunction pci1xxxx_gpio_set_wakefunction pci1xxxx_gpio_irq_handlerfunction for_each_set_bitfunction pci1xxxx_gpio_suspendfunction pci1xxxx_gpio_resumefunction pci1xxxx_gpio_setupfunction pci1xxxx_gpio_probe
Annotated Snippet
struct pci1xxxx_gpio {
struct auxiliary_device *aux_dev;
void __iomem *reg_base;
raw_spinlock_t wa_lock;
struct gpio_chip gpio;
spinlock_t lock;
u32 gpio_wake_mask[3];
int irq_base;
u8 dev_rev;
};
static int pci1xxxx_gpio_get_device_revision(struct pci1xxxx_gpio *priv)
{
struct device *parent = priv->aux_dev->dev.parent;
struct pci_dev *pcidev = to_pci_dev(parent);
int ret;
u32 val;
ret = pci_read_config_dword(pcidev, PCI_DEV_REV_OFFSET, &val);
if (ret)
return ret;
priv->dev_rev = val;
return 0;
}
static int pci1xxxx_gpio_get_direction(struct gpio_chip *gpio, unsigned int nr)
{
struct pci1xxxx_gpio *priv = gpiochip_get_data(gpio);
u32 data;
int ret = -EINVAL;
data = readl(priv->reg_base + INP_EN_OFFSET(nr));
if (data & BIT(nr % 32)) {
ret = 1;
} else {
data = readl(priv->reg_base + OUT_EN_OFFSET(nr));
if (data & BIT(nr % 32))
ret = 0;
}
return ret;
}
static inline void pci1xxx_assign_bit(void __iomem *base_addr, unsigned int reg_offset,
unsigned int bitpos, bool set)
{
u32 data;
data = readl(base_addr + reg_offset);
if (set)
data |= BIT(bitpos);
else
data &= ~BIT(bitpos);
writel(data, base_addr + reg_offset);
}
static int pci1xxxx_gpio_direction_input(struct gpio_chip *gpio, unsigned int nr)
{
struct pci1xxxx_gpio *priv = gpiochip_get_data(gpio);
unsigned long flags;
spin_lock_irqsave(&priv->lock, flags);
pci1xxx_assign_bit(priv->reg_base, INP_EN_OFFSET(nr), (nr % 32), true);
pci1xxx_assign_bit(priv->reg_base, OUT_EN_OFFSET(nr), (nr % 32), false);
spin_unlock_irqrestore(&priv->lock, flags);
return 0;
}
static int pci1xxxx_gpio_get(struct gpio_chip *gpio, unsigned int nr)
{
struct pci1xxxx_gpio *priv = gpiochip_get_data(gpio);
return (readl(priv->reg_base + INP_OFFSET(nr)) >> (nr % 32)) & 1;
}
static int pci1xxxx_gpio_direction_output(struct gpio_chip *gpio,
unsigned int nr, int val)
{
struct pci1xxxx_gpio *priv = gpiochip_get_data(gpio);
unsigned long flags;
u32 data;
spin_lock_irqsave(&priv->lock, flags);
pci1xxx_assign_bit(priv->reg_base, INP_EN_OFFSET(nr), (nr % 32), false);
pci1xxx_assign_bit(priv->reg_base, OUT_EN_OFFSET(nr), (nr % 32), true);
data = readl(priv->reg_base + OUT_OFFSET(nr));
if (val)
Annotation
- Immediate include surface: `linux/module.h`, `linux/spinlock.h`, `linux/gpio/driver.h`, `linux/bio.h`, `linux/mutex.h`, `linux/pci.h`, `linux/kthread.h`, `linux/interrupt.h`.
- Detected declarations: `struct pci1xxxx_gpio`, `function pci1xxxx_gpio_get_device_revision`, `function pci1xxxx_gpio_get_direction`, `function pci1xxx_assign_bit`, `function pci1xxxx_gpio_direction_input`, `function pci1xxxx_gpio_get`, `function pci1xxxx_gpio_direction_output`, `function pci1xxxx_gpio_set`, `function pci1xxxx_gpio_set_config`, `function pci1xxxx_gpio_irq_ack`.
- Atlas domain: Driver Families / drivers/misc.
- Implementation status: source implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
- IRQ or DMA behavior appears here, which is relevant to the selected PCIe/NVMe device path.
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.