drivers/gpio/gpio-104-dio-48e.c

Source file repositories/reference/linux-study-clean/drivers/gpio/gpio-104-dio-48e.c

File Facts

System
Linux kernel
Corpus path
drivers/gpio/gpio-104-dio-48e.c
Extension
.c
Size
10593 bytes
Lines
343
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 dio48e_gpio {
	raw_spinlock_t lock;
	struct regmap *map;
	void __iomem *regs;
	unsigned long flags;
	unsigned int irq_mask;
};

static void dio48e_regmap_lock(void *lock_arg) __acquires(&dio48egpio->lock)
{
	struct dio48e_gpio *const dio48egpio = lock_arg;
	unsigned long flags;

	raw_spin_lock_irqsave(&dio48egpio->lock, flags);
	dio48egpio->flags = flags;
}

static void dio48e_regmap_unlock(void *lock_arg) __releases(&dio48egpio->lock)
{
	struct dio48e_gpio *const dio48egpio = lock_arg;

	raw_spin_unlock_irqrestore(&dio48egpio->lock, dio48egpio->flags);
}

static void pit_regmap_lock(void *lock_arg) __acquires(&dio48egpio->lock)
{
	struct dio48e_gpio *const dio48egpio = lock_arg;
	unsigned long flags;

	raw_spin_lock_irqsave(&dio48egpio->lock, flags);
	dio48egpio->flags = flags;

	iowrite8(0x00, dio48egpio->regs + DIO48E_ENABLE_COUNTER_TIMER_ADDRESSING);
}

static void pit_regmap_unlock(void *lock_arg) __releases(&dio48egpio->lock)
{
	struct dio48e_gpio *const dio48egpio = lock_arg;

	ioread8(dio48egpio->regs + DIO48E_DISABLE_COUNTER_TIMER_ADDRESSING);

	raw_spin_unlock_irqrestore(&dio48egpio->lock, dio48egpio->flags);
}

static int dio48e_handle_mask_sync(const int index,
				   const unsigned int mask_buf_def,
				   const unsigned int mask_buf,
				   void *const irq_drv_data)
{
	struct dio48e_gpio *const dio48egpio = irq_drv_data;
	const unsigned int prev_mask = dio48egpio->irq_mask;
	int err;
	unsigned int val;

	/* exit early if no change since the previous mask */
	if (mask_buf == prev_mask)
		return 0;

	/* remember the current mask for the next mask sync */
	dio48egpio->irq_mask = mask_buf;

	/* if all previously masked, enable interrupts when unmasking */
	if (prev_mask == mask_buf_def) {
		err = regmap_write(dio48egpio->map, DIO48E_CLEAR_INTERRUPT, 0x00);
		if (err)
			return err;
		return regmap_write(dio48egpio->map, DIO48E_ENABLE_INTERRUPT, 0x00);
	}

	/* if all are currently masked, disable interrupts */
	if (mask_buf == mask_buf_def)
		return regmap_read(dio48egpio->map, DIO48E_DISABLE_INTERRUPT, &val);

	return 0;
}

#define DIO48E_NGPIO 48
static const char *dio48e_names[DIO48E_NGPIO] = {
	"PPI Group 0 Port A 0", "PPI Group 0 Port A 1", "PPI Group 0 Port A 2",
	"PPI Group 0 Port A 3", "PPI Group 0 Port A 4", "PPI Group 0 Port A 5",
	"PPI Group 0 Port A 6", "PPI Group 0 Port A 7",	"PPI Group 0 Port B 0",
	"PPI Group 0 Port B 1", "PPI Group 0 Port B 2", "PPI Group 0 Port B 3",
	"PPI Group 0 Port B 4", "PPI Group 0 Port B 5", "PPI Group 0 Port B 6",
	"PPI Group 0 Port B 7", "PPI Group 0 Port C 0", "PPI Group 0 Port C 1",
	"PPI Group 0 Port C 2", "PPI Group 0 Port C 3", "PPI Group 0 Port C 4",
	"PPI Group 0 Port C 5", "PPI Group 0 Port C 6", "PPI Group 0 Port C 7",
	"PPI Group 1 Port A 0", "PPI Group 1 Port A 1", "PPI Group 1 Port A 2",
	"PPI Group 1 Port A 3", "PPI Group 1 Port A 4", "PPI Group 1 Port A 5",
	"PPI Group 1 Port A 6", "PPI Group 1 Port A 7",	"PPI Group 1 Port B 0",
	"PPI Group 1 Port B 1", "PPI Group 1 Port B 2", "PPI Group 1 Port B 3",

Annotation

Implementation Notes