drivers/gpio/gpio-lp3943.c

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

File Facts

System
Linux kernel
Corpus path
drivers/gpio/gpio-lp3943.c
Extension
.c
Size
5500 bytes
Lines
230
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 lp3943_gpio {
	struct gpio_chip chip;
	struct lp3943 *lp3943;
	u16 input_mask;		/* 1 = GPIO is input direction, 0 = output */
};

static int lp3943_gpio_request(struct gpio_chip *chip, unsigned int offset)
{
	struct lp3943_gpio *lp3943_gpio = gpiochip_get_data(chip);
	struct lp3943 *lp3943 = lp3943_gpio->lp3943;

	/* Return an error if the pin is already assigned */
	if (test_and_set_bit(offset, &lp3943->pin_used))
		return -EBUSY;

	return 0;
}

static void lp3943_gpio_free(struct gpio_chip *chip, unsigned int offset)
{
	struct lp3943_gpio *lp3943_gpio = gpiochip_get_data(chip);
	struct lp3943 *lp3943 = lp3943_gpio->lp3943;

	clear_bit(offset, &lp3943->pin_used);
}

static int lp3943_gpio_set_mode(struct lp3943_gpio *lp3943_gpio, u8 offset,
				u8 val)
{
	struct lp3943 *lp3943 = lp3943_gpio->lp3943;
	const struct lp3943_reg_cfg *mux = lp3943->mux_cfg;

	return lp3943_update_bits(lp3943, mux[offset].reg, mux[offset].mask,
				  val << mux[offset].shift);
}

static int lp3943_gpio_direction_input(struct gpio_chip *chip, unsigned int offset)
{
	struct lp3943_gpio *lp3943_gpio = gpiochip_get_data(chip);

	lp3943_gpio->input_mask |= BIT(offset);

	return lp3943_gpio_set_mode(lp3943_gpio, offset, LP3943_GPIO_IN);
}

static int lp3943_get_gpio_in_status(struct lp3943_gpio *lp3943_gpio,
				     struct gpio_chip *chip, unsigned int offset)
{
	u8 addr, read;
	int err;

	switch (offset) {
	case LP3943_GPIO1 ... LP3943_GPIO8:
		addr = LP3943_REG_GPIO_A;
		break;
	case LP3943_GPIO9 ... LP3943_GPIO16:
		addr = LP3943_REG_GPIO_B;
		offset = offset - 8;
		break;
	default:
		return -EINVAL;
	}

	err = lp3943_read_byte(lp3943_gpio->lp3943, addr, &read);
	if (err)
		return err;

	return !!(read & BIT(offset));
}

static int lp3943_get_gpio_out_status(struct lp3943_gpio *lp3943_gpio,
				      struct gpio_chip *chip, unsigned int offset)
{
	struct lp3943 *lp3943 = lp3943_gpio->lp3943;
	const struct lp3943_reg_cfg *mux = lp3943->mux_cfg;
	u8 read;
	int err;

	err = lp3943_read_byte(lp3943, mux[offset].reg, &read);
	if (err)
		return err;

	read = (read & mux[offset].mask) >> mux[offset].shift;

	if (read == LP3943_GPIO_OUT_HIGH)
		return 1;
	else if (read == LP3943_GPIO_OUT_LOW)
		return 0;
	else
		return -EINVAL;

Annotation

Implementation Notes