drivers/gpio/gpio-max7360.c

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

File Facts

System
Linux kernel
Corpus path
drivers/gpio/gpio-max7360.c
Extension
.c
Size
7460 bytes
Lines
258
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 max7360_gpio_plat_data {
	unsigned int function;
};

static struct max7360_gpio_plat_data max7360_gpio_port_plat = { .function = MAX7360_GPIO_PORT };
static struct max7360_gpio_plat_data max7360_gpio_col_plat = { .function = MAX7360_GPIO_COL };

static int max7360_get_available_gpos(struct device *dev, unsigned int *available_gpios)
{
	u32 columns;
	int ret;

	ret = device_property_read_u32(dev->parent, "keypad,num-columns", &columns);
	if (ret) {
		dev_err(dev, "Failed to read columns count\n");
		return ret;
	}

	*available_gpios = min(MAX7360_MAX_GPO, MAX7360_MAX_KEY_COLS - columns);

	return 0;
}

static int max7360_gpo_init_valid_mask(struct gpio_chip *gc,
				       unsigned long *valid_mask,
				       unsigned int ngpios)
{
	unsigned int available_gpios;
	int ret;

	ret = max7360_get_available_gpos(gc->parent, &available_gpios);
	if (ret)
		return ret;

	bitmap_clear(valid_mask, 0, MAX7360_MAX_KEY_COLS - available_gpios);

	return 0;
}

static int max7360_set_gpos_count(struct device *dev, struct regmap *regmap)
{
	/*
	 * MAX7360 COL0 to COL7 pins can be used either as keypad columns,
	 * general purpose output or a mix of both.
	 * By default, all pins are used as keypad, here we update this
	 * configuration to allow to use some of them as GPIOs.
	 */
	unsigned int available_gpios;
	unsigned int val;
	int ret;

	ret = max7360_get_available_gpos(dev, &available_gpios);
	if (ret)
		return ret;

	/*
	 * Configure which GPIOs will be used for keypad.
	 * MAX7360_REG_DEBOUNCE contains configuration both for keypad debounce
	 * timings and gpos/keypad columns repartition. Only the later is
	 * modified here.
	 */
	val = FIELD_PREP(MAX7360_PORTS, available_gpios);
	ret = regmap_write_bits(regmap, MAX7360_REG_DEBOUNCE, MAX7360_PORTS, val);
	if (ret)
		dev_err(dev, "Failed to write max7360 columns/gpos configuration");

	return ret;
}

static int max7360_gpio_reg_mask_xlate(struct gpio_regmap *gpio,
				       unsigned int base, unsigned int offset,
				       unsigned int *reg, unsigned int *mask)
{
	if (base == MAX7360_REG_PWMBASE) {
		/*
		 * GPIO output is using PWM duty cycle registers: one register
		 * per line, with value being either 0 or 255.
		 */
		*reg = base + offset;
		*mask = GENMASK(7, 0);
	} else {
		*reg = base;
		*mask = BIT(offset);
	}

	return 0;
}

static const struct regmap_irq max7360_regmap_irqs[MAX7360_MAX_GPIO] = {
	REGMAP_IRQ_REG(0, 0, BIT(0)),

Annotation

Implementation Notes