drivers/gpio/gpio-kempld.c

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

File Facts

System
Linux kernel
Corpus path
drivers/gpio/gpio-kempld.c
Extension
.c
Size
12015 bytes
Lines
467
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.

Dependency Surface

Detected Declarations

Annotated Snippet

struct kempld_gpio_data {
	struct gpio_chip		chip;
	struct kempld_device_data	*pld;
	u8				out_lvl_reg;

	struct mutex			irq_lock;
	u16				ien;
	u16				evt_low_high;
	u16				evt_lvl_edge;
};

/*
 * Set or clear GPIO bit
 * kempld_get_mutex must be called prior to calling this function.
 */
static void kempld_gpio_bitop(struct kempld_device_data *pld,
			      u8 reg, unsigned int bit, bool val)
{
	u8 status;

	status = kempld_read8(pld, reg + (bit / 8));
	if (val)
		status |= KEMPLD_GPIO_MASK(bit);
	else
		status &= ~KEMPLD_GPIO_MASK(bit);
	kempld_write8(pld, reg + (bit / 8), status);
}

static int kempld_gpio_get_bit(struct kempld_device_data *pld,
			       u8 reg, unsigned int bit)
{
	u8 status;

	kempld_get_mutex(pld);
	status = kempld_read8(pld, reg + (bit / 8));
	kempld_release_mutex(pld);

	return !!(status & KEMPLD_GPIO_MASK(bit));
}

static int kempld_gpio_get(struct gpio_chip *chip, unsigned offset)
{
	struct kempld_gpio_data *gpio = gpiochip_get_data(chip);
	struct kempld_device_data *pld = gpio->pld;

	return !!kempld_gpio_get_bit(pld, KEMPLD_GPIO_LVL, offset);
}

static int kempld_gpio_get_multiple(struct gpio_chip *chip, unsigned long *mask,
				    unsigned long *bits)
{
	struct kempld_gpio_data *gpio = gpiochip_get_data(chip);
	struct kempld_device_data *pld = gpio->pld;
	u8 reg = KEMPLD_GPIO_LVL;
	unsigned int shift;

	bits[0] &= ~mask[0];

	kempld_get_mutex(pld);

	/* Try to reduce to a single 8 bits access if possible */
	for (shift = 0; shift < gpio->chip.ngpio; shift += 8, reg++) {
		unsigned long msk = (mask[0] >> shift) & 0xff;

		if (!msk)
			continue;

		bits[0] |= (kempld_read8(pld, reg) & msk) << shift;
	}

	kempld_release_mutex(pld);

	return 0;
}

static int kempld_gpio_set(struct gpio_chip *chip, unsigned int offset,
			   int value)
{
	struct kempld_gpio_data *gpio = gpiochip_get_data(chip);
	struct kempld_device_data *pld = gpio->pld;

	kempld_get_mutex(pld);
	kempld_gpio_bitop(pld, gpio->out_lvl_reg, offset, value);
	kempld_release_mutex(pld);

	return 0;
}

static int kempld_gpio_set_multiple(struct gpio_chip *chip,
				    unsigned long *mask, unsigned long *bits)

Annotation

Implementation Notes