drivers/gpio/gpio-eic-sprd.c

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

File Facts

System
Linux kernel
Corpus path
drivers/gpio/gpio-eic-sprd.c
Extension
.c
Size
20911 bytes
Lines
738
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 sprd_eic {
	struct gpio_chip chip;
	struct notifier_block irq_nb;
	void __iomem *base[SPRD_EIC_MAX_BANK];
	enum sprd_eic_type type;
	spinlock_t lock;
	int irq;
};

static ATOMIC_NOTIFIER_HEAD(sprd_eic_irq_notifier);

static struct sprd_eic *to_sprd_eic(struct notifier_block *nb)
{
	return container_of(nb, struct sprd_eic, irq_nb);
}

struct sprd_eic_variant_data {
	enum sprd_eic_type type;
};

static const char *sprd_eic_label_name[SPRD_EIC_MAX] = {
	"eic-debounce", "eic-latch", "eic-async",
	"eic-sync",
};

static const struct sprd_eic_variant_data sc9860_eic_dbnc_data = {
	.type = SPRD_EIC_DEBOUNCE,
};

static const struct sprd_eic_variant_data sc9860_eic_latch_data = {
	.type = SPRD_EIC_LATCH,
};

static const struct sprd_eic_variant_data sc9860_eic_async_data = {
	.type = SPRD_EIC_ASYNC,
};

static const struct sprd_eic_variant_data sc9860_eic_sync_data = {
	.type = SPRD_EIC_SYNC,
};

static inline void __iomem *sprd_eic_offset_base(struct sprd_eic *sprd_eic,
						 unsigned int bank)
{
	if (bank >= SPRD_EIC_MAX_BANK)
		return NULL;

	return sprd_eic->base[bank];
}

static void sprd_eic_update(struct gpio_chip *chip, unsigned int offset,
			    u16 reg, unsigned int val)
{
	struct sprd_eic *sprd_eic = gpiochip_get_data(chip);
	void __iomem *base =
		sprd_eic_offset_base(sprd_eic, offset / SPRD_EIC_PER_BANK_NR);
	unsigned long flags;
	u32 tmp;

	spin_lock_irqsave(&sprd_eic->lock, flags);
	tmp = readl_relaxed(base + reg);

	if (val)
		tmp |= BIT(SPRD_EIC_BIT(offset));
	else
		tmp &= ~BIT(SPRD_EIC_BIT(offset));

	writel_relaxed(tmp, base + reg);
	spin_unlock_irqrestore(&sprd_eic->lock, flags);
}

static int sprd_eic_read(struct gpio_chip *chip, unsigned int offset, u16 reg)
{
	struct sprd_eic *sprd_eic = gpiochip_get_data(chip);
	void __iomem *base =
		sprd_eic_offset_base(sprd_eic, offset / SPRD_EIC_PER_BANK_NR);

	return !!(readl_relaxed(base + reg) & BIT(SPRD_EIC_BIT(offset)));
}

static int sprd_eic_request(struct gpio_chip *chip, unsigned int offset)
{
	sprd_eic_update(chip, offset, SPRD_EIC_DBNC_DMSK, 1);
	return 0;
}

static void sprd_eic_free(struct gpio_chip *chip, unsigned int offset)
{
	sprd_eic_update(chip, offset, SPRD_EIC_DBNC_DMSK, 0);
}

Annotation

Implementation Notes