drivers/gpio/gpio-usbio.c

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

File Facts

System
Linux kernel
Corpus path
drivers/gpio/gpio-usbio.c
Extension
.c
Size
6658 bytes
Lines
250
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 usbio_gpio_bank {
	u8 config[USBIO_GPIOSPERBANK];
	u32 bitmap;
};

struct usbio_gpio {
	struct mutex config_mutex; /* Protects banks[x].config */
	struct usbio_gpio_bank banks[USBIO_MAX_GPIOBANKS];
	struct gpio_chip gc;
	struct auxiliary_device *adev;
};

static const struct acpi_device_id usbio_gpio_acpi_hids[] = {
	{ "INTC1007" }, /* MTL */
	{ "INTC10B2" }, /* ARL */
	{ "INTC10B5" }, /* LNL */
	{ "INTC10D1" }, /* MTL-CVF */
	{ "INTC10E2" }, /* PTL */
	{ "INTC1116" }, /* NVL */
	{ }
};

static void usbio_gpio_get_bank_and_pin(struct gpio_chip *gc, unsigned int offset,
					struct usbio_gpio_bank **bank_ret,
					unsigned int *pin_ret)
{
	struct usbio_gpio *gpio = gpiochip_get_data(gc);
	struct device *dev = &gpio->adev->dev;
	struct usbio_gpio_bank *bank;
	unsigned int pin;

	bank = &gpio->banks[offset / USBIO_GPIOSPERBANK];
	pin = offset % USBIO_GPIOSPERBANK;
	if (~bank->bitmap & BIT(pin)) {
		/* The FW bitmap sometimes is invalid, warn and continue */
		dev_warn_once(dev, FW_BUG "GPIO %u is not in FW pins bitmap\n", offset);
	}

	*bank_ret = bank;
	*pin_ret = pin;
}

static int usbio_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
{
	struct usbio_gpio_bank *bank;
	unsigned int pin;
	u8 cfg;

	usbio_gpio_get_bank_and_pin(gc, offset, &bank, &pin);

	cfg = bank->config[pin] & USBIO_GPIO_PINMOD_MASK;

	return (cfg == USBIO_GPIO_PINMOD_OUTPUT) ?
		GPIO_LINE_DIRECTION_OUT : GPIO_LINE_DIRECTION_IN;
}

static int usbio_gpio_get(struct gpio_chip *gc, unsigned int offset)
{
	struct usbio_gpio *gpio = gpiochip_get_data(gc);
	struct usbio_gpio_bank *bank;
	struct usbio_gpio_rw gbuf;
	unsigned int pin;
	int ret;

	usbio_gpio_get_bank_and_pin(gc, offset, &bank, &pin);

	gbuf.bankid = offset / USBIO_GPIOSPERBANK;
	gbuf.pincount  = 1;
	gbuf.pin = pin;

	ret = usbio_control_msg(gpio->adev, USBIO_PKTTYPE_GPIO, USBIO_GPIOCMD_READ,
				&gbuf, sizeof(gbuf) - sizeof(gbuf.value),
				&gbuf, sizeof(gbuf));
	if (ret != sizeof(gbuf))
		return (ret < 0) ? ret : -EPROTO;

	return (le32_to_cpu(gbuf.value) >> pin) & 1;
}

static int usbio_gpio_set(struct gpio_chip *gc, unsigned int offset, int value)
{
	struct usbio_gpio *gpio = gpiochip_get_data(gc);
	struct usbio_gpio_bank *bank;
	struct usbio_gpio_rw gbuf;
	unsigned int pin;

	usbio_gpio_get_bank_and_pin(gc, offset, &bank, &pin);

	gbuf.bankid = offset / USBIO_GPIOSPERBANK;
	gbuf.pincount  = 1;

Annotation

Implementation Notes