drivers/pinctrl/nuvoton/pinctrl-wpcm450.c

Source file repositories/reference/linux-study-clean/drivers/pinctrl/nuvoton/pinctrl-wpcm450.c

File Facts

System
Linux kernel
Corpus path
drivers/pinctrl/nuvoton/pinctrl-wpcm450.c
Extension
.c
Size
36386 bytes
Lines
1168
Domain
Driver Families
Bucket
drivers/pinctrl
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 wpcm450_gpio {
	struct gpio_generic_chip chip;
	struct wpcm450_pinctrl	*pctrl;
	const struct wpcm450_bank *bank;
};

struct wpcm450_pinctrl {
	struct pinctrl_dev	*pctldev;
	struct device		*dev;
	struct irq_domain	*domain;
	struct regmap		*gcr_regmap;
	void __iomem		*gpio_base;
	struct wpcm450_gpio	gpio_bank[WPCM450_NUM_BANKS];
	unsigned long		both_edges;

	/*
	 * This spin lock protects registers and struct wpcm450_pinctrl fields
	 * against concurrent access.
	 */
	raw_spinlock_t		lock;
};

struct wpcm450_bank {
	/* Range of GPIOs in this port */
	u8 base;
	u8 length;

	/* Register offsets (0 = register doesn't exist in this port) */
	u8 cfg0, cfg1, cfg2;
	u8 blink;
	u8 dataout, datain;

	/* Interrupt bit mapping */
	u8 first_irq_bit;   /* First bit in GPEVST that belongs to this bank */
	u8 num_irqs;        /* Number of IRQ-capable GPIOs in this bank */
	u8 first_irq_gpio;  /* First IRQ-capable GPIO in this bank */
};

static const struct wpcm450_bank wpcm450_banks[WPCM450_NUM_BANKS] = {
	/*  range   cfg0  cfg1  cfg2 blink  out   in     IRQ map */
	{   0, 16,  0x14, 0x18,    0,    0, 0x1c, 0x20,  0, 16, 0 },
	{  16, 16,  0x24, 0x28, 0x2c, 0x30, 0x34, 0x38, 16,  2, 8 },
	{  32, 16,  0x3c, 0x40, 0x44,    0, 0x48, 0x4c,  0,  0, 0 },
	{  48, 16,  0x50, 0x54, 0x58,    0, 0x5c, 0x60,  0,  0, 0 },
	{  64, 16,  0x64, 0x68, 0x6c,    0, 0x70, 0x74,  0,  0, 0 },
	{  80, 16,  0x78, 0x7c, 0x80,    0, 0x84, 0x88,  0,  0, 0 },
	{  96, 18,     0,    0,    0,    0,    0, 0x8c,  0,  0, 0 },
	{ 114, 14,  0x90, 0x94, 0x98,    0, 0x9c, 0xa0,  0,  0, 0 },
};

static int wpcm450_gpio_irq_bitnum(struct wpcm450_gpio *gpio, struct irq_data *d)
{
	const struct wpcm450_bank *bank = gpio->bank;
	int hwirq = irqd_to_hwirq(d);

	if (hwirq < bank->first_irq_gpio)
		return -EINVAL;

	if (hwirq - bank->first_irq_gpio >= bank->num_irqs)
		return -EINVAL;

	return hwirq - bank->first_irq_gpio + bank->first_irq_bit;
}

static int wpcm450_irq_bitnum_to_gpio(struct wpcm450_gpio *gpio, int bitnum)
{
	const struct wpcm450_bank *bank = gpio->bank;

	if (bitnum < bank->first_irq_bit)
		return -EINVAL;

	if (bitnum - bank->first_irq_bit > bank->num_irqs)
		return -EINVAL;

	return bitnum - bank->first_irq_bit + bank->first_irq_gpio;
}

static void wpcm450_gpio_irq_ack(struct irq_data *d)
{
	struct wpcm450_gpio *gpio = gpiochip_get_data(irq_data_get_irq_chip_data(d));
	struct wpcm450_pinctrl *pctrl = gpio->pctrl;
	unsigned long flags;
	int bit;

	bit = wpcm450_gpio_irq_bitnum(gpio, d);
	if (bit < 0)
		return;

	raw_spin_lock_irqsave(&pctrl->lock, flags);
	iowrite32(BIT(bit), pctrl->gpio_base + WPCM450_GPEVST);

Annotation

Implementation Notes