drivers/mux/mmio.c

Source file repositories/reference/linux-study-clean/drivers/mux/mmio.c

File Facts

System
Linux kernel
Corpus path
drivers/mux/mmio.c
Extension
.c
Size
5705 bytes
Lines
225
Domain
Driver Families
Bucket
drivers/mux
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 mux_mmio {
	struct regmap_field **fields;
	unsigned int *hardware_states;
};

static int mux_mmio_get(struct mux_control *mux, int *state)
{
	struct mux_mmio *mux_mmio = mux_chip_priv(mux->chip);
	unsigned int index = mux_control_get_index(mux);

	return regmap_field_read(mux_mmio->fields[index], state);
}

static int mux_mmio_set(struct mux_control *mux, int state)
{
	struct mux_mmio *mux_mmio = mux_chip_priv(mux->chip);
	unsigned int index = mux_control_get_index(mux);

	return regmap_field_write(mux_mmio->fields[index], state);
}

static const struct mux_control_ops mux_mmio_ops = {
	.set = mux_mmio_set,
};

static const struct of_device_id mux_mmio_dt_ids[] = {
	{ .compatible = "mmio-mux", },
	{ .compatible = "reg-mux", },
	{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, mux_mmio_dt_ids);

static const struct regmap_config mux_mmio_regmap_cfg = {
	.reg_bits = 32,
	.val_bits = 32,
	.reg_stride = 4,
};

static int mux_mmio_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct device_node *np = dev->of_node;
	struct mux_chip *mux_chip;
	struct mux_mmio *mux_mmio;
	struct regmap *regmap;
	void __iomem *base;
	int num_fields;
	int ret;
	int i;

	if (of_device_is_compatible(np, "mmio-mux")) {
		regmap = syscon_node_to_regmap(np->parent);
	} else {
		base = devm_platform_ioremap_resource(pdev, 0);
		if (IS_ERR(base))
			regmap = ERR_PTR(-ENODEV);
		else
			regmap = devm_regmap_init_mmio(dev, base, &mux_mmio_regmap_cfg);
		/* Fallback to checking the parent node on "real" errors. */
		if (IS_ERR(regmap) && regmap != ERR_PTR(-EPROBE_DEFER)) {
			regmap = dev_get_regmap(dev->parent, NULL);
			if (!regmap)
				regmap = ERR_PTR(-ENODEV);
		}
	}
	if (IS_ERR(regmap))
		return dev_err_probe(dev, PTR_ERR(regmap),
				     "failed to get regmap\n");

	ret = of_property_count_u32_elems(np, "mux-reg-masks");
	if (ret == 0 || ret % 2)
		ret = -EINVAL;
	if (ret < 0) {
		dev_err(dev, "mux-reg-masks property missing or invalid: %d\n",
			ret);
		return ret;
	}
	num_fields = ret / 2;

	mux_chip = devm_mux_chip_alloc(dev, num_fields, sizeof(struct mux_mmio));
	if (IS_ERR(mux_chip))
		return PTR_ERR(mux_chip);

	mux_mmio = mux_chip_priv(mux_chip);

	mux_mmio->fields = devm_kcalloc(dev, num_fields, sizeof(*mux_mmio->fields),
					GFP_KERNEL);
	if (!mux_mmio->fields)
		return -ENOMEM;

Annotation

Implementation Notes