drivers/gpio/gpio-exar.c
Source file repositories/reference/linux-study-clean/drivers/gpio/gpio-exar.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/gpio/gpio-exar.c- Extension
.c- Size
- 6696 bytes
- Lines
- 240
- 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.
- 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/bitops.hlinux/device.hlinux/gpio/driver.hlinux/idr.hlinux/init.hlinux/kernel.hlinux/module.hlinux/pci.hlinux/platform_device.hlinux/regmap.h
Detected Declarations
struct exar_gpio_chipfunction exar_offset_to_sel_addrfunction exar_offset_to_lvl_addrfunction exar_offset_to_bitfunction exar_get_directionfunction exar_get_valuefunction exar_set_valuefunction exar_direction_outputfunction exar_direction_inputfunction exar_devm_ida_freefunction gpio_exar_probe
Annotated Snippet
struct exar_gpio_chip {
struct gpio_chip gpio_chip;
struct regmap *regmap;
int index;
char name[20];
unsigned int first_pin;
/*
* The offset to the cascaded device's (if existing)
* Device Configuration Registers.
*/
unsigned int cascaded_offset;
};
static unsigned int
exar_offset_to_sel_addr(struct exar_gpio_chip *exar_gpio, unsigned int offset)
{
unsigned int pin = exar_gpio->first_pin + (offset % 16);
unsigned int cascaded = offset / 16;
unsigned int addr = pin / 8 ? EXAR_OFFSET_MPIOSEL_HI : EXAR_OFFSET_MPIOSEL_LO;
return addr + (cascaded ? exar_gpio->cascaded_offset : 0);
}
static unsigned int
exar_offset_to_lvl_addr(struct exar_gpio_chip *exar_gpio, unsigned int offset)
{
unsigned int pin = exar_gpio->first_pin + (offset % 16);
unsigned int cascaded = offset / 16;
unsigned int addr = pin / 8 ? EXAR_OFFSET_MPIOLVL_HI : EXAR_OFFSET_MPIOLVL_LO;
return addr + (cascaded ? exar_gpio->cascaded_offset : 0);
}
static unsigned int
exar_offset_to_bit(struct exar_gpio_chip *exar_gpio, unsigned int offset)
{
unsigned int pin = exar_gpio->first_pin + (offset % 16);
return pin % 8;
}
static int exar_get_direction(struct gpio_chip *chip, unsigned int offset)
{
struct exar_gpio_chip *exar_gpio = gpiochip_get_data(chip);
unsigned int addr = exar_offset_to_sel_addr(exar_gpio, offset);
unsigned int bit = exar_offset_to_bit(exar_gpio, offset);
if (regmap_test_bits(exar_gpio->regmap, addr, BIT(bit)))
return GPIO_LINE_DIRECTION_IN;
return GPIO_LINE_DIRECTION_OUT;
}
static int exar_get_value(struct gpio_chip *chip, unsigned int offset)
{
struct exar_gpio_chip *exar_gpio = gpiochip_get_data(chip);
unsigned int addr = exar_offset_to_lvl_addr(exar_gpio, offset);
unsigned int bit = exar_offset_to_bit(exar_gpio, offset);
return !!(regmap_test_bits(exar_gpio->regmap, addr, BIT(bit)));
}
static int exar_set_value(struct gpio_chip *chip, unsigned int offset,
int value)
{
struct exar_gpio_chip *exar_gpio = gpiochip_get_data(chip);
unsigned int addr = exar_offset_to_lvl_addr(exar_gpio, offset);
unsigned int bit = exar_offset_to_bit(exar_gpio, offset);
unsigned int bit_value = value ? BIT(bit) : 0;
/*
* regmap_write_bits() forces value to be written when an external
* pull up/down might otherwise indicate value was already set.
*/
return regmap_write_bits(exar_gpio->regmap, addr, BIT(bit), bit_value);
}
static int exar_direction_output(struct gpio_chip *chip, unsigned int offset,
int value)
{
struct exar_gpio_chip *exar_gpio = gpiochip_get_data(chip);
unsigned int addr = exar_offset_to_sel_addr(exar_gpio, offset);
unsigned int bit = exar_offset_to_bit(exar_gpio, offset);
int ret;
ret = exar_set_value(chip, offset, value);
if (ret)
return ret;
return regmap_clear_bits(exar_gpio->regmap, addr, BIT(bit));
Annotation
- Immediate include surface: `linux/bitops.h`, `linux/device.h`, `linux/gpio/driver.h`, `linux/idr.h`, `linux/init.h`, `linux/kernel.h`, `linux/module.h`, `linux/pci.h`.
- Detected declarations: `struct exar_gpio_chip`, `function exar_offset_to_sel_addr`, `function exar_offset_to_lvl_addr`, `function exar_offset_to_bit`, `function exar_get_direction`, `function exar_get_value`, `function exar_set_value`, `function exar_direction_output`, `function exar_direction_input`, `function exar_devm_ida_free`.
- Atlas domain: Driver Families / drivers/gpio.
- Implementation status: source implementation candidate.
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.