drivers/gpio/gpio-hisi.c

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

File Facts

System
Linux kernel
Corpus path
drivers/gpio/gpio-hisi.c
Extension
.c
Size
9938 bytes
Lines
344
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 hisi_gpio {
	struct gpio_generic_chip chip;
	struct device		*dev;
	void __iomem		*reg_base;
	unsigned int		line_num;
	int			irq;
};

static inline u32 hisi_gpio_read_reg(struct gpio_chip *chip,
				     unsigned int off)
{
	struct hisi_gpio *hisi_gpio = container_of(to_gpio_generic_chip(chip),
						   struct hisi_gpio, chip);
	void __iomem *reg = hisi_gpio->reg_base + off;

	return readl(reg);
}

static inline void hisi_gpio_write_reg(struct gpio_chip *chip,
				       unsigned int off, u32 val)
{
	struct hisi_gpio *hisi_gpio = container_of(to_gpio_generic_chip(chip),
						   struct hisi_gpio, chip);
	void __iomem *reg = hisi_gpio->reg_base + off;

	writel(val, reg);
}

static void hisi_gpio_set_debounce(struct gpio_chip *chip, unsigned int off,
				   u32 debounce)
{
	if (debounce)
		hisi_gpio_write_reg(chip, HISI_GPIO_DEBOUNCE_SET_WX, BIT(off));
	else
		hisi_gpio_write_reg(chip, HISI_GPIO_DEBOUNCE_CLR_WX, BIT(off));
}

static int hisi_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
				unsigned long config)
{
	u32 config_para = pinconf_to_config_param(config);
	u32 config_arg;

	switch (config_para) {
	case PIN_CONFIG_INPUT_DEBOUNCE:
		config_arg = pinconf_to_config_argument(config);
		hisi_gpio_set_debounce(chip, offset, config_arg);
		break;
	default:
		return -ENOTSUPP;
	}

	return 0;
}

static void hisi_gpio_set_ack(struct irq_data *d)
{
	struct gpio_chip *chip = irq_data_get_irq_chip_data(d);

	hisi_gpio_write_reg(chip, HISI_GPIO_PORTA_EOI_WX, BIT(irqd_to_hwirq(d)));
}

static void hisi_gpio_irq_set_mask(struct irq_data *d)
{
	struct gpio_chip *chip = irq_data_get_irq_chip_data(d);

	hisi_gpio_write_reg(chip, HISI_GPIO_INTMASK_SET_WX, BIT(irqd_to_hwirq(d)));
	gpiochip_disable_irq(chip, irqd_to_hwirq(d));
}

static void hisi_gpio_irq_clr_mask(struct irq_data *d)
{
	struct gpio_chip *chip = irq_data_get_irq_chip_data(d);

	gpiochip_enable_irq(chip, irqd_to_hwirq(d));
	hisi_gpio_write_reg(chip, HISI_GPIO_INTMASK_CLR_WX, BIT(irqd_to_hwirq(d)));
}

static int hisi_gpio_irq_set_type(struct irq_data *d, u32 type)
{
	struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
	unsigned int mask = BIT(irqd_to_hwirq(d));

	switch (type) {
	case IRQ_TYPE_EDGE_BOTH:
		hisi_gpio_write_reg(chip, HISI_GPIO_INT_DEDGE_SET, mask);
		break;
	case IRQ_TYPE_EDGE_RISING:
		hisi_gpio_write_reg(chip, HISI_GPIO_INTTYPE_EDGE_SET_WX, mask);
		hisi_gpio_write_reg(chip, HISI_GPIO_INT_POLARITY_SET_WX, mask);

Annotation

Implementation Notes