drivers/mfd/stmfx.c

Source file repositories/reference/linux-study-clean/drivers/mfd/stmfx.c

File Facts

System
Linux kernel
Corpus path
drivers/mfd/stmfx.c
Extension
.c
Size
13378 bytes
Lines
562
Domain
Driver Families
Bucket
drivers/mfd
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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

if (ret) {
			dev_err(&client->dev, "VDD enable failed: %d\n", ret);
			return ret;
		}
	}

	ret = regmap_read(stmfx->map, STMFX_REG_CHIP_ID, &id);
	if (ret) {
		dev_err(&client->dev, "Error reading chip ID: %d\n", ret);
		goto err;
	}

	/*
	 * Check that ID is the complement of the I2C address:
	 * STMFX I2C address follows the 7-bit format (MSB), that's why
	 * client->addr is shifted.
	 *
	 * STMFX_I2C_ADDR|       STMFX         |        Linux
	 *   input pin   | I2C device address  | I2C device address
	 *---------------------------------------------------------
	 *       0       | b: 1000 010x h:0x84 |       0x42
	 *       1       | b: 1000 011x h:0x86 |       0x43
	 */
	if (FIELD_GET(STMFX_REG_CHIP_ID_MASK, ~id) != (client->addr << 1)) {
		dev_err(&client->dev, "Unknown chip ID: %#x\n", id);
		ret = -EINVAL;
		goto err;
	}

	ret = regmap_bulk_read(stmfx->map, STMFX_REG_FW_VERSION_MSB,
			       version, ARRAY_SIZE(version));
	if (ret) {
		dev_err(&client->dev, "Error reading FW version: %d\n", ret);
		goto err;
	}

	dev_info(&client->dev, "STMFX id: %#x, fw version: %x.%02x\n",
		 id, version[0], version[1]);

	ret = stmfx_chip_reset(stmfx);
	if (ret) {
		dev_err(&client->dev, "Failed to reset chip: %d\n", ret);
		goto err;
	}

	return 0;

err:
	if (stmfx->vdd)
		regulator_disable(stmfx->vdd);

	return ret;
}

static void stmfx_chip_exit(struct i2c_client *client)
{
	struct stmfx *stmfx = i2c_get_clientdata(client);

	regmap_write(stmfx->map, STMFX_REG_IRQ_SRC_EN, 0);
	regmap_write(stmfx->map, STMFX_REG_SYS_CTRL, 0);

	if (stmfx->vdd) {
		int ret;

		ret = regulator_disable(stmfx->vdd);
		if (ret)
			dev_err(&client->dev,
				"Failed to disable vdd regulator: %pe\n",
				ERR_PTR(ret));
	}
}

static int stmfx_probe(struct i2c_client *client)
{
	struct device *dev = &client->dev;
	struct stmfx *stmfx;
	int ret;

	stmfx = devm_kzalloc(dev, sizeof(*stmfx), GFP_KERNEL);
	if (!stmfx)
		return -ENOMEM;

	i2c_set_clientdata(client, stmfx);

	stmfx->dev = dev;

	stmfx->map = devm_regmap_init_i2c(client, &stmfx_regmap_config);
	if (IS_ERR(stmfx->map)) {
		ret = PTR_ERR(stmfx->map);
		dev_err(dev, "Failed to allocate register map: %d\n", ret);

Annotation

Implementation Notes