Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 193304ae authored by Peter Rosin's avatar Peter Rosin Committed by Wolfram Sang
Browse files

i2c: i2c-mux-reg: convert to use an explicit i2c mux core



Allocate an explicit i2c mux core to handle parent and child adapters
etc. Update the select/deselect ops to be in terms of the i2c mux core
instead of the child adapter.

Signed-off-by: default avatarPeter Rosin <peda@axentia.se>
Signed-off-by: default avatarWolfram Sang <wsa@the-dreams.de>
parent 7fcac980
Loading
Loading
Loading
Loading
+25 −44
Original line number Diff line number Diff line
@@ -21,8 +21,6 @@
#include <linux/slab.h>

struct regmux {
	struct i2c_adapter *parent;
	struct i2c_adapter **adap; /* child busses */
	struct i2c_mux_reg_platform_data data;
};

@@ -64,18 +62,16 @@ static int i2c_mux_reg_set(const struct regmux *mux, unsigned int chan_id)
	return 0;
}

static int i2c_mux_reg_select(struct i2c_adapter *adap, void *data,
			      unsigned int chan)
static int i2c_mux_reg_select(struct i2c_mux_core *muxc, u32 chan)
{
	struct regmux *mux = data;
	struct regmux *mux = i2c_mux_priv(muxc);

	return i2c_mux_reg_set(mux, chan);
}

static int i2c_mux_reg_deselect(struct i2c_adapter *adap, void *data,
				unsigned int chan)
static int i2c_mux_reg_deselect(struct i2c_mux_core *muxc, u32 chan)
{
	struct regmux *mux = data;
	struct regmux *mux = i2c_mux_priv(muxc);

	if (mux->data.idle_in_use)
		return i2c_mux_reg_set(mux, mux->data.idle);
@@ -107,7 +103,6 @@ static int i2c_mux_reg_probe_dt(struct regmux *mux,
	if (!adapter)
		return -EPROBE_DEFER;

	mux->parent = adapter;
	mux->data.parent = i2c_adapter_id(adapter);
	put_device(&adapter->dev);

@@ -169,10 +164,10 @@ static int i2c_mux_reg_probe_dt(struct regmux *mux,

static int i2c_mux_reg_probe(struct platform_device *pdev)
{
	struct i2c_mux_core *muxc;
	struct regmux *mux;
	struct i2c_adapter *parent;
	struct resource *res;
	int (*deselect)(struct i2c_adapter *, void *, u32);
	unsigned int class;
	int i, ret, nr;

@@ -180,17 +175,9 @@ static int i2c_mux_reg_probe(struct platform_device *pdev)
	if (!mux)
		return -ENOMEM;

	platform_set_drvdata(pdev, mux);

	if (dev_get_platdata(&pdev->dev)) {
		memcpy(&mux->data, dev_get_platdata(&pdev->dev),
			sizeof(mux->data));

		parent = i2c_get_adapter(mux->data.parent);
		if (!parent)
			return -EPROBE_DEFER;

		mux->parent = parent;
	} else {
		ret = i2c_mux_reg_probe_dt(mux, pdev);
		if (ret < 0) {
@@ -199,6 +186,10 @@ static int i2c_mux_reg_probe(struct platform_device *pdev)
		}
	}

	parent = i2c_get_adapter(mux->data.parent);
	if (!parent)
		return -EPROBE_DEFER;

	if (!mux->data.reg) {
		dev_info(&pdev->dev,
			"Register not set, using platform resource\n");
@@ -215,55 +206,45 @@ static int i2c_mux_reg_probe(struct platform_device *pdev)
		return -EINVAL;
	}

	mux->adap = devm_kzalloc(&pdev->dev,
				 sizeof(*mux->adap) * mux->data.n_values,
				 GFP_KERNEL);
	if (!mux->adap) {
		dev_err(&pdev->dev, "Cannot allocate i2c_adapter structure");
	muxc = i2c_mux_alloc(parent, &pdev->dev, mux->data.n_values, 0, 0,
			     i2c_mux_reg_select, NULL);
	if (!muxc)
		return -ENOMEM;
	}
	muxc->priv = mux;

	platform_set_drvdata(pdev, muxc);

	if (mux->data.idle_in_use)
		deselect = i2c_mux_reg_deselect;
	else
		deselect = NULL;
		muxc->deselect = i2c_mux_reg_deselect;

	for (i = 0; i < mux->data.n_values; i++) {
		nr = mux->data.base_nr ? (mux->data.base_nr + i) : 0;
		class = mux->data.classes ? mux->data.classes[i] : 0;

		mux->adap[i] = i2c_add_mux_adapter(mux->parent, &pdev->dev, mux,
						   nr, mux->data.values[i],
						   class, i2c_mux_reg_select,
						   deselect);
		if (!mux->adap[i]) {
			ret = -ENODEV;
		ret = i2c_mux_add_adapter(muxc, nr, mux->data.values[i], class);
		if (ret) {
			dev_err(&pdev->dev, "Failed to add adapter %d\n", i);
			goto add_adapter_failed;
		}
	}

	dev_dbg(&pdev->dev, "%d port mux on %s adapter\n",
		 mux->data.n_values, mux->parent->name);
		 mux->data.n_values, muxc->parent->name);

	return 0;

add_adapter_failed:
	for (; i > 0; i--)
		i2c_del_mux_adapter(mux->adap[i - 1]);
	i2c_mux_del_adapters(muxc);

	return ret;
}

static int i2c_mux_reg_remove(struct platform_device *pdev)
{
	struct regmux *mux = platform_get_drvdata(pdev);
	int i;

	for (i = 0; i < mux->data.n_values; i++)
		i2c_del_mux_adapter(mux->adap[i]);
	struct i2c_mux_core *muxc = platform_get_drvdata(pdev);

	i2c_put_adapter(mux->parent);
	i2c_mux_del_adapters(muxc);
	i2c_put_adapter(muxc->parent);

	return 0;
}