drivers/gpio/gpio-nct6694.c

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

File Facts

System
Linux kernel
Corpus path
drivers/gpio/gpio-nct6694.c
Extension
.c
Size
12562 bytes
Lines
500
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 nct6694_gpio_data {
	struct nct6694 *nct6694;
	struct gpio_chip gpio;
	struct mutex lock;
	/* Protect irq operation */
	struct mutex irq_lock;

	unsigned char reg_val;
	unsigned char irq_trig_falling;
	unsigned char irq_trig_rising;

	/* Current gpio group */
	unsigned char group;
	int irq;
};

static int nct6694_get_direction(struct gpio_chip *gpio, unsigned int offset)
{
	struct nct6694_gpio_data *data = gpiochip_get_data(gpio);
	const struct nct6694_cmd_header cmd_hd = {
		.mod = NCT6694_GPIO_MOD,
		.offset = cpu_to_le16(NCT6694_GPO_DIR + data->group),
		.len = cpu_to_le16(sizeof(data->reg_val))
	};
	int ret;

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

	ret = nct6694_read_msg(data->nct6694, &cmd_hd, &data->reg_val);
	if (ret < 0)
		return ret;

	return !(BIT(offset) & data->reg_val);
}

static int nct6694_direction_input(struct gpio_chip *gpio, unsigned int offset)
{
	struct nct6694_gpio_data *data = gpiochip_get_data(gpio);
	const struct nct6694_cmd_header cmd_hd = {
		.mod = NCT6694_GPIO_MOD,
		.offset = cpu_to_le16(NCT6694_GPO_DIR + data->group),
		.len = cpu_to_le16(sizeof(data->reg_val))
	};
	int ret;

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

	ret = nct6694_read_msg(data->nct6694, &cmd_hd, &data->reg_val);
	if (ret < 0)
		return ret;

	data->reg_val &= ~BIT(offset);

	return nct6694_write_msg(data->nct6694, &cmd_hd, &data->reg_val);
}

static int nct6694_direction_output(struct gpio_chip *gpio,
				    unsigned int offset, int val)
{
	struct nct6694_gpio_data *data = gpiochip_get_data(gpio);
	struct nct6694_cmd_header cmd_hd = {
		.mod = NCT6694_GPIO_MOD,
		.offset = cpu_to_le16(NCT6694_GPO_DIR + data->group),
		.len = cpu_to_le16(sizeof(data->reg_val))
	};
	int ret;

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

	/* Set direction to output */
	ret = nct6694_read_msg(data->nct6694, &cmd_hd, &data->reg_val);
	if (ret < 0)
		return ret;

	data->reg_val |= BIT(offset);
	ret = nct6694_write_msg(data->nct6694, &cmd_hd, &data->reg_val);
	if (ret < 0)
		return ret;

	/* Then set output level */
	cmd_hd.offset = cpu_to_le16(NCT6694_GPO_DATA + data->group);
	ret = nct6694_read_msg(data->nct6694, &cmd_hd, &data->reg_val);
	if (ret < 0)
		return ret;

	if (val)
		data->reg_val |= BIT(offset);
	else
		data->reg_val &= ~BIT(offset);

Annotation

Implementation Notes