drivers/gpio/gpio-da9052.c

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

File Facts

System
Linux kernel
Corpus path
drivers/gpio/gpio-da9052.c
Extension
.c
Size
5536 bytes
Lines
216
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 da9052_gpio {
	struct da9052 *da9052;
	struct gpio_chip gp;
};

static unsigned char da9052_gpio_port_odd(unsigned offset)
{
	return offset % 2;
}

static int da9052_gpio_get(struct gpio_chip *gc, unsigned offset)
{
	struct da9052_gpio *gpio = gpiochip_get_data(gc);
	int da9052_port_direction = 0;
	int ret;

	ret = da9052_reg_read(gpio->da9052,
			      DA9052_GPIO_0_1_REG + (offset >> 1));
	if (ret < 0)
		return ret;

	if (da9052_gpio_port_odd(offset)) {
		da9052_port_direction = ret & DA9052_GPIO_ODD_PORT_PIN;
		da9052_port_direction >>= 4;
	} else {
		da9052_port_direction = ret & DA9052_GPIO_EVEN_PORT_PIN;
	}

	switch (da9052_port_direction) {
	case DA9052_INPUT:
		if (offset < DA9052_GPIO_MAX_PORTS_PER_REGISTER)
			ret = da9052_reg_read(gpio->da9052,
					      DA9052_STATUS_C_REG);
		else
			ret = da9052_reg_read(gpio->da9052,
					      DA9052_STATUS_D_REG);
		if (ret < 0)
			return ret;
		return !!(ret & (1 << DA9052_GPIO_SHIFT_COUNT(offset)));
	case DA9052_OUTPUT_PUSHPULL:
		if (da9052_gpio_port_odd(offset))
			return !!(ret & DA9052_GPIO_ODD_PORT_MODE);
		else
			return !!(ret & DA9052_GPIO_EVEN_PORT_MODE);
	default:
		return -EINVAL;
	}
}

static int da9052_gpio_set(struct gpio_chip *gc, unsigned int offset, int value)
{
	struct da9052_gpio *gpio = gpiochip_get_data(gc);

	if (da9052_gpio_port_odd(offset))
		return da9052_reg_update(gpio->da9052, (offset >> 1) +
					 DA9052_GPIO_0_1_REG,
					 DA9052_GPIO_ODD_PORT_MODE,
					 value << DA9052_GPIO_ODD_SHIFT);

	return da9052_reg_update(gpio->da9052,
				 (offset >> 1) + DA9052_GPIO_0_1_REG,
				 DA9052_GPIO_EVEN_PORT_MODE,
				 value << DA9052_GPIO_EVEN_SHIFT);
}

static int da9052_gpio_direction_input(struct gpio_chip *gc, unsigned offset)
{
	struct da9052_gpio *gpio = gpiochip_get_data(gc);
	unsigned char register_value;
	int ret;

	/* Format: function - 2 bits type - 1 bit mode - 1 bit */
	register_value = DA9052_INPUT | DA9052_ACTIVE_LOW << 2 |
			 DA9052_DEBOUNCING_ON << 3;

	if (da9052_gpio_port_odd(offset))
		ret = da9052_reg_update(gpio->da9052, (offset >> 1) +
					DA9052_GPIO_0_1_REG,
					DA9052_GPIO_MASK_UPPER_NIBBLE,
					(register_value <<
					DA9052_GPIO_NIBBLE_SHIFT));
	else
		ret = da9052_reg_update(gpio->da9052, (offset >> 1) +
					DA9052_GPIO_0_1_REG,
					DA9052_GPIO_MASK_LOWER_NIBBLE,
					register_value);

	return ret;
}

Annotation

Implementation Notes