drivers/i2c/muxes/i2c-mux-mule.c

Source file repositories/reference/linux-study-clean/drivers/i2c/muxes/i2c-mux-mule.c

File Facts

System
Linux kernel
Corpus path
drivers/i2c/muxes/i2c-mux-mule.c
Extension
.c
Size
3755 bytes
Lines
148
Domain
Driver Families
Bucket
drivers/i2c
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 mule_i2c_reg_mux {
	struct regmap *regmap;
};

static int mule_i2c_mux_select(struct i2c_mux_core *muxc, u32 dev)
{
	struct mule_i2c_reg_mux *mux = muxc->priv;

	return regmap_write(mux->regmap, MULE_I2C_MUX_CONFIG_REG, dev);
}

static int mule_i2c_mux_deselect(struct i2c_mux_core *muxc, u32 dev)
{
	return mule_i2c_mux_select(muxc, MULE_I2C_MUX_DEFAULT_DEV);
}

static void mule_i2c_mux_remove(void *data)
{
	struct i2c_mux_core *muxc = data;

	i2c_mux_del_adapters(muxc);

	mule_i2c_mux_deselect(muxc, MULE_I2C_MUX_DEFAULT_DEV);
}

static int mule_i2c_mux_probe(struct platform_device *pdev)
{
	struct device *mux_dev = &pdev->dev;
	struct mule_i2c_reg_mux *priv;
	struct i2c_client *client;
	struct i2c_mux_core *muxc;
	unsigned int readback;
	int ndev, ret;
	bool old_fw;

	/* Count devices on the mux */
	ndev = of_get_child_count(mux_dev->of_node);
	dev_dbg(mux_dev, "%d devices on the mux\n", ndev);

	client = to_i2c_client(mux_dev->parent);

	muxc = i2c_mux_alloc(client->adapter, mux_dev, ndev, sizeof(*priv),
			     I2C_MUX_LOCKED, mule_i2c_mux_select, mule_i2c_mux_deselect);
	if (!muxc)
		return -ENOMEM;

	priv = i2c_mux_priv(muxc);

	priv->regmap = dev_get_regmap(mux_dev->parent, NULL);
	if (!priv->regmap)
		return dev_err_probe(mux_dev, -ENODEV,
				     "No parent i2c register map\n");

	platform_set_drvdata(pdev, muxc);

	/*
	 * MULE_I2C_MUX_DEFAULT_DEV is guaranteed to exist on all old and new
	 * mule fw. Mule fw without mux support will accept write ops to the
	 * config register, but readback returns 0xff (register not updated).
	 */
	ret = mule_i2c_mux_select(muxc, MULE_I2C_MUX_DEFAULT_DEV);
	if (ret)
		return dev_err_probe(mux_dev, ret,
				     "Failed to write config register\n");

	ret = regmap_read(priv->regmap, MULE_I2C_MUX_CONFIG_REG, &readback);
	if (ret)
		return dev_err_probe(mux_dev, ret,
				     "Failed to read config register\n");

	old_fw = (readback != MULE_I2C_MUX_DEFAULT_DEV);

	ret = devm_add_action_or_reset(mux_dev, mule_i2c_mux_remove, muxc);
	if (ret)
		return dev_err_probe(mux_dev, ret,
				     "Failed to register mux remove\n");

	/* Create device adapters */
	for_each_child_of_node_scoped(mux_dev->of_node, dev) {
		u32 reg;

		ret = of_property_read_u32(dev, "reg", &reg);
		if (ret)
			return dev_err_probe(mux_dev, ret,
					     "No reg property found for %s\n",
					     of_node_full_name(dev));

		if (old_fw && reg != 0) {
			dev_warn(mux_dev,
				 "Mux is not supported, please update Mule FW\n");

Annotation

Implementation Notes