drivers/gpio/gpio-sprd.c

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

File Facts

System
Linux kernel
Corpus path
drivers/gpio/gpio-sprd.c
Extension
.c
Size
8040 bytes
Lines
282
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_gpio {
	struct gpio_chip chip;
	void __iomem *base;
	raw_spinlock_t lock;
	int irq;
};

static inline void __iomem *sprd_gpio_bank_base(struct sprd_gpio *sprd_gpio,
						unsigned int bank)
{
	return sprd_gpio->base + SPRD_GPIO_BANK_SIZE * bank;
}

static void sprd_gpio_update(struct gpio_chip *chip, unsigned int offset,
			     u16 reg, int val)
{
	struct sprd_gpio *sprd_gpio = gpiochip_get_data(chip);
	void __iomem *base = sprd_gpio_bank_base(sprd_gpio,
						 offset / SPRD_GPIO_BANK_NR);
	unsigned long flags;
	u32 tmp;

	raw_spin_lock_irqsave(&sprd_gpio->lock, flags);
	tmp = readl_relaxed(base + reg);

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

	writel_relaxed(tmp, base + reg);
	raw_spin_unlock_irqrestore(&sprd_gpio->lock, flags);
}

static int sprd_gpio_read(struct gpio_chip *chip, unsigned int offset, u16 reg)
{
	struct sprd_gpio *sprd_gpio = gpiochip_get_data(chip);
	void __iomem *base = sprd_gpio_bank_base(sprd_gpio,
						 offset / SPRD_GPIO_BANK_NR);

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

static int sprd_gpio_request(struct gpio_chip *chip, unsigned int offset)
{
	sprd_gpio_update(chip, offset, SPRD_GPIO_DMSK, 1);
	return 0;
}

static void sprd_gpio_free(struct gpio_chip *chip, unsigned int offset)
{
	sprd_gpio_update(chip, offset, SPRD_GPIO_DMSK, 0);
}

static int sprd_gpio_direction_input(struct gpio_chip *chip,
				     unsigned int offset)
{
	sprd_gpio_update(chip, offset, SPRD_GPIO_DIR, 0);
	sprd_gpio_update(chip, offset, SPRD_GPIO_INEN, 1);
	return 0;
}

static int sprd_gpio_direction_output(struct gpio_chip *chip,
				      unsigned int offset, int value)
{
	sprd_gpio_update(chip, offset, SPRD_GPIO_DIR, 1);
	sprd_gpio_update(chip, offset, SPRD_GPIO_INEN, 0);
	sprd_gpio_update(chip, offset, SPRD_GPIO_DATA, value);
	return 0;
}

static int sprd_gpio_get(struct gpio_chip *chip, unsigned int offset)
{
	return sprd_gpio_read(chip, offset, SPRD_GPIO_DATA);
}

static int sprd_gpio_set(struct gpio_chip *chip, unsigned int offset,
			 int value)
{
	sprd_gpio_update(chip, offset, SPRD_GPIO_DATA, value);

	return 0;
}

static void sprd_gpio_irq_mask(struct irq_data *data)
{
	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
	u32 offset = irqd_to_hwirq(data);

	sprd_gpio_update(chip, offset, SPRD_GPIO_IE, 0);

Annotation

Implementation Notes