drivers/gpio/gpio-tangier.c

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

File Facts

System
Linux kernel
Corpus path
drivers/gpio/gpio-tangier.c
Extension
.c
Size
13328 bytes
Lines
519
Domain
Driver Families
Bucket
drivers/gpio
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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 tng_gpio_context {
	u32 level;
	u32 gpdr;
	u32 grer;
	u32 gfer;
	u32 gimr;
	u32 gwmr;
};

static void __iomem *gpio_reg(struct gpio_chip *chip, unsigned int offset,
			      unsigned int reg)
{
	struct tng_gpio *priv = gpiochip_get_data(chip);
	u8 reg_offset = offset / 32;

	return priv->reg_base + reg + reg_offset * 4;
}

static void __iomem *gpio_reg_and_bit(struct gpio_chip *chip, unsigned int offset,
				      unsigned int reg, u8 *bit)
{
	struct tng_gpio *priv = gpiochip_get_data(chip);
	u8 reg_offset = offset / 32;
	u8 shift = offset % 32;

	*bit = shift;
	return priv->reg_base + reg + reg_offset * 4;
}

static int tng_gpio_get(struct gpio_chip *chip, unsigned int offset)
{
	void __iomem *gplr;
	u8 shift;

	gplr = gpio_reg_and_bit(chip, offset, GPLR, &shift);

	return !!(readl(gplr) & BIT(shift));
}

static int tng_gpio_set(struct gpio_chip *chip, unsigned int offset, int value)
{
	struct tng_gpio *priv = gpiochip_get_data(chip);
	void __iomem *reg;
	u8 shift;

	reg = gpio_reg_and_bit(chip, offset, value ? GPSR : GPCR, &shift);

	guard(raw_spinlock_irqsave)(&priv->lock);

	writel(BIT(shift), reg);

	return 0;
}

static int tng_gpio_direction_input(struct gpio_chip *chip, unsigned int offset)
{
	struct tng_gpio *priv = gpiochip_get_data(chip);
	void __iomem *gpdr;
	u32 value;
	u8 shift;

	gpdr = gpio_reg_and_bit(chip, offset, GPDR, &shift);

	guard(raw_spinlock_irqsave)(&priv->lock);

	value = readl(gpdr);
	value &= ~BIT(shift);
	writel(value, gpdr);

	return 0;
}

static int tng_gpio_direction_output(struct gpio_chip *chip, unsigned int offset,
				     int value)
{
	struct tng_gpio *priv = gpiochip_get_data(chip);
	void __iomem *gpdr;
	u8 shift;

	gpdr = gpio_reg_and_bit(chip, offset, GPDR, &shift);
	tng_gpio_set(chip, offset, value);

	guard(raw_spinlock_irqsave)(&priv->lock);

	value = readl(gpdr);
	value |= BIT(shift);
	writel(value, gpdr);

	return 0;
}

Annotation

Implementation Notes