drivers/gpio/gpio-cgbc.c

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

File Facts

System
Linux kernel
Corpus path
drivers/gpio/gpio-cgbc.c
Extension
.c
Size
4740 bytes
Lines
201
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 cgbc_gpio_data {
	struct gpio_chip	chip;
	struct cgbc_device_data	*cgbc;
	struct mutex lock;
};

static int cgbc_gpio_cmd(struct cgbc_device_data *cgbc,
			 u8 cmd0, u8 cmd1, u8 cmd2, u8 *value)
{
	u8 cmd[3] = {cmd0, cmd1, cmd2};

	return cgbc_command(cgbc, cmd, sizeof(cmd), value, 1, NULL);
}

static int cgbc_gpio_get(struct gpio_chip *chip, unsigned int offset)
{
	struct cgbc_gpio_data *gpio = gpiochip_get_data(chip);
	struct cgbc_device_data *cgbc = gpio->cgbc;
	int ret;
	u8 val;

	scoped_guard(mutex, &gpio->lock)
		ret = cgbc_gpio_cmd(cgbc, CGBC_GPIO_CMD_GET, (offset > 7) ? 1 : 0, 0, &val);

	offset %= 8;

	if (ret)
		return ret;

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

static int __cgbc_gpio_set(struct gpio_chip *chip, unsigned int offset,
			   int value)
{
	struct cgbc_gpio_data *gpio = gpiochip_get_data(chip);
	struct cgbc_device_data *cgbc = gpio->cgbc;
	u8 val;
	int ret;

	ret = cgbc_gpio_cmd(cgbc, CGBC_GPIO_CMD_GET, (offset > 7) ? 1 : 0, 0, &val);
	if (ret)
		return ret;

	if (value)
		val |= BIT(offset % 8);
	else
		val &= ~(BIT(offset % 8));

	return cgbc_gpio_cmd(cgbc, CGBC_GPIO_CMD_SET, (offset > 7) ? 1 : 0, val, &val);
}

static int cgbc_gpio_set(struct gpio_chip *chip, unsigned int offset, int value)
{
	struct cgbc_gpio_data *gpio = gpiochip_get_data(chip);

	guard(mutex)(&gpio->lock);

	return __cgbc_gpio_set(chip, offset, value);
}

static int cgbc_gpio_direction_set(struct gpio_chip *chip,
				   unsigned int offset, int direction)
{
	struct cgbc_gpio_data *gpio = gpiochip_get_data(chip);
	struct cgbc_device_data *cgbc = gpio->cgbc;
	int ret;
	u8 val;

	ret = cgbc_gpio_cmd(cgbc, CGBC_GPIO_CMD_DIR_GET, (offset > 7) ? 1 : 0, 0, &val);
	if (ret)
		goto end;

	if (direction == GPIO_LINE_DIRECTION_IN)
		val &= ~(BIT(offset % 8));
	else
		val |= BIT(offset % 8);

	ret = cgbc_gpio_cmd(cgbc, CGBC_GPIO_CMD_DIR_SET, (offset > 7) ? 1 : 0, val, &val);

end:
	return ret;
}

static int cgbc_gpio_direction_input(struct gpio_chip *chip,
				     unsigned int offset)
{
	struct cgbc_gpio_data *gpio = gpiochip_get_data(chip);

	guard(mutex)(&gpio->lock);

Annotation

Implementation Notes