drivers/gpio/gpio-ts4900.c

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

File Facts

System
Linux kernel
Corpus path
drivers/gpio/gpio-ts4900.c
Extension
.c
Size
4958 bytes
Lines
196
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 ts4900_gpio_priv {
	struct regmap *regmap;
	struct gpio_chip gpio_chip;
	unsigned int input_bit;
};

static int ts4900_gpio_get_direction(struct gpio_chip *chip,
				     unsigned int offset)
{
	struct ts4900_gpio_priv *priv = gpiochip_get_data(chip);
	unsigned int reg;

	regmap_read(priv->regmap, offset, &reg);

	if (reg & TS4900_GPIO_OE)
		return GPIO_LINE_DIRECTION_OUT;

	return GPIO_LINE_DIRECTION_IN;
}

static int ts4900_gpio_direction_input(struct gpio_chip *chip,
				       unsigned int offset)
{
	struct ts4900_gpio_priv *priv = gpiochip_get_data(chip);

	/*
	 * Only clear the OE bit here, requires a RMW. Prevents a potential issue
	 * with OE and DAT getting to the physical pin at different times.
	 */
	return regmap_update_bits(priv->regmap, offset, TS4900_GPIO_OE, 0);
}

static int ts4900_gpio_direction_output(struct gpio_chip *chip,
					unsigned int offset, int value)
{
	struct ts4900_gpio_priv *priv = gpiochip_get_data(chip);
	unsigned int reg;
	int ret;

	/*
	 * If changing from an input to an output, we need to first set the
	 * GPIO's DAT bit to what is requested and then set the OE bit. This
	 * prevents a glitch that can occur on the IO line.
	 */
	regmap_read(priv->regmap, offset, &reg);
	if (!(reg & TS4900_GPIO_OE)) {
		if (value)
			reg = TS4900_GPIO_OUT;
		else
			reg &= ~TS4900_GPIO_OUT;

		regmap_write(priv->regmap, offset, reg);
	}

	if (value)
		ret = regmap_write(priv->regmap, offset, TS4900_GPIO_OE |
							 TS4900_GPIO_OUT);
	else
		ret = regmap_write(priv->regmap, offset, TS4900_GPIO_OE);

	return ret;
}

static int ts4900_gpio_get(struct gpio_chip *chip, unsigned int offset)
{
	struct ts4900_gpio_priv *priv = gpiochip_get_data(chip);
	unsigned int reg;

	regmap_read(priv->regmap, offset, &reg);

	return !!(reg & priv->input_bit);
}

static int ts4900_gpio_set(struct gpio_chip *chip, unsigned int offset,
			   int value)
{
	struct ts4900_gpio_priv *priv = gpiochip_get_data(chip);

	if (value)
		return regmap_update_bits(priv->regmap, offset,
					  TS4900_GPIO_OUT, TS4900_GPIO_OUT);

	return regmap_update_bits(priv->regmap, offset, TS4900_GPIO_OUT, 0);
}

static const struct regmap_config ts4900_regmap_config = {
	.reg_bits = 16,
	.val_bits = 8,
};

Annotation

Implementation Notes