drivers/misc/ti_fpc202.c

Source file repositories/reference/linux-study-clean/drivers/misc/ti_fpc202.c

File Facts

System
Linux kernel
Corpus path
drivers/misc/ti_fpc202.c
Extension
.c
Size
19285 bytes
Lines
740
Domain
Driver Families
Bucket
drivers/misc
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 fpc202_led {
	int offset;
	struct led_classdev led_cdev;
	struct fpc202_priv *priv;
	struct gpio_desc *gpio;
	enum fpc202_led_mode mode;
};

struct fpc202_priv {
	struct i2c_client *client;
	struct i2c_atr *atr;
	struct gpio_desc *en_gpio;
	struct gpio_chip gpio;
	struct fpc202_led leds[FPC202_LED_COUNT];

	/* Lock REG_MOD/AUX_DEV and addr_caches during attach/detach */
	struct mutex reg_dev_lock;

	/* Lock LED mode select register during accesses */
	struct mutex led_mode_lock;

	/* Cached device addresses for both ports and their devices */
	u8 addr_caches[2][2];

	/* Keep track of which ports were probed */
	DECLARE_BITMAP(probed_ports, FPC202_NUM_PORTS);
};

static void fpc202_fill_alias_table(struct i2c_client *client, u16 *aliases, int port_id)
{
	u16 first_alias;
	int i;

	/*
	 * There is a predefined list of aliases for each FPC202 I2C
	 * self-address.  This allows daisy-chained FPC202 units to
	 * automatically take on different sets of aliases.
	 * Each port of an FPC202 unit is assigned two aliases from this list.
	 */
	first_alias = 0x10 + 4 * port_id + 8 * ((u16)client->addr - 2);

	for (i = 0; i < FPC202_ALIASES_PER_PORT; i++)
		aliases[i] = first_alias + i;
}

static int fpc202_gpio_get_dir(int offset)
{
	return offset < FPC202_GPIO_P0_S0_OUT_A ? GPIO_LINE_DIRECTION_IN : GPIO_LINE_DIRECTION_OUT;
}

static int fpc202_gpio_has_led_caps(int offset)
{
	return offset >= FPC202_GPIO_P0_S0_OUT_C;
}

static int fpc202_read(struct fpc202_priv *priv, u8 reg)
{
	int val;

	val = i2c_smbus_read_byte_data(priv->client, reg);
	return val;
}

static int fpc202_write(struct fpc202_priv *priv, u8 reg, u8 value)
{
	return i2c_smbus_write_byte_data(priv->client, reg, value);
}

static void fpc202_set_enable(struct fpc202_priv *priv, int enable)
{
	if (!priv->en_gpio)
		return;

	gpiod_set_value(priv->en_gpio, enable);
}

static int fpc202_led_mode_write(struct fpc202_priv *priv,
				 int offset,
				 enum fpc202_led_mode mode)
{
	u8 val, reg = FPC202_REG_LED_MODE(offset);
	int ret;

	guard(mutex)(&priv->led_mode_lock);

	ret = fpc202_read(priv, reg);
	if (ret < 0) {
		dev_err(&priv->client->dev, "failed to read LED mode %d! err %d\n",
			offset, ret);
		return ret;

Annotation

Implementation Notes