drivers/gpio/gpio-bd71815.c

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

File Facts

System
Linux kernel
Corpus path
drivers/gpio/gpio-bd71815.c
Extension
.c
Size
5163 bytes
Lines
183
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 bd71815_gpio {
	/* chip.parent points the MFD which provides DT node and regmap */
	struct gpio_chip chip;
	/* dev points to the platform device for devm and prints */
	struct device *dev;
	struct regmap *regmap;
};

static int bd71815gpo_get(struct gpio_chip *chip, unsigned int offset)
{
	struct bd71815_gpio *bd71815 = gpiochip_get_data(chip);
	int ret, val;

	ret = regmap_read(bd71815->regmap, BD71815_REG_GPO, &val);
	if (ret)
		return ret;

	return (val >> offset) & 1;
}

static int bd71815gpo_set(struct gpio_chip *chip, unsigned int offset,
			  int value)
{
	struct bd71815_gpio *bd71815 = gpiochip_get_data(chip);
	int bit;

	bit = BIT(offset);

	if (value)
		return regmap_set_bits(bd71815->regmap, BD71815_REG_GPO, bit);

	return regmap_clear_bits(bd71815->regmap, BD71815_REG_GPO, bit);
}

static int bd71815_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
				   unsigned long config)
{
	struct bd71815_gpio *bdgpio = gpiochip_get_data(chip);

	switch (pinconf_to_config_param(config)) {
	case PIN_CONFIG_DRIVE_OPEN_DRAIN:
		return regmap_update_bits(bdgpio->regmap,
					  BD71815_REG_GPO,
					  BD71815_GPIO_DRIVE_MASK << offset,
					  BD71815_GPIO_OPEN_DRAIN << offset);
	case PIN_CONFIG_DRIVE_PUSH_PULL:
		return regmap_update_bits(bdgpio->regmap,
					  BD71815_REG_GPO,
					  BD71815_GPIO_DRIVE_MASK << offset,
					  BD71815_GPIO_CMOS << offset);
	default:
		break;
	}
	return -ENOTSUPP;
}

/* BD71815 GPIO is actually GPO */
static int bd71815gpo_direction_get(struct gpio_chip *gc, unsigned int offset)
{
	return GPIO_LINE_DIRECTION_OUT;
}

/* Template for GPIO chip */
static const struct gpio_chip bd71815gpo_chip = {
	.label			= "bd71815",
	.owner			= THIS_MODULE,
	.get			= bd71815gpo_get,
	.get_direction		= bd71815gpo_direction_get,
	.set			= bd71815gpo_set,
	.set_config		= bd71815_gpio_set_config,
	.can_sleep		= true,
};

#define BD71815_TWO_GPIOS	GENMASK(1, 0)
#define BD71815_ONE_GPIO	BIT(0)

/*
 * Sigh. The BD71815 and BD71817 were originally designed to support two GPO
 * pins. At some point it was noticed the second GPO pin which is the E5 pin
 * located at the center of IC is hard to use on PCB (due to the location). It
 * was decided to not promote this second GPO and the pin is marked as GND in
 * the datasheet. The functionality is still there though! I guess driving a GPO
 * connected to the ground is a bad idea. Thus we do not support it by default.
 * OTOH - the original driver written by colleagues at Embest did support
 * controlling this second GPO. It is thus possible this is used in some of the
 * products.
 *
 * This driver does not by default support configuring this second GPO
 * but allows using it by providing the DT property
 * "rohm,enable-hidden-gpo".

Annotation

Implementation Notes