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

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

i2c: i2c-mux-gpio: 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 a7ab7239
Loading
Loading
Loading
Loading
+22 −33
Original line number Diff line number Diff line
@@ -18,8 +18,6 @@
#include <linux/of_gpio.h>

struct gpiomux {
	struct i2c_adapter *parent;
	struct i2c_adapter **adap; /* child busses */
	struct i2c_mux_gpio_platform_data data;
	unsigned gpio_base;
};
@@ -33,18 +31,18 @@ static void i2c_mux_gpio_set(const struct gpiomux *mux, unsigned val)
					val & (1 << i));
}

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

	i2c_mux_gpio_set(mux, chan);

	return 0;
}

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

	i2c_mux_gpio_set(mux, mux->data.idle);

@@ -136,19 +134,15 @@ static int i2c_mux_gpio_probe_dt(struct gpiomux *mux,

static int i2c_mux_gpio_probe(struct platform_device *pdev)
{
	struct i2c_mux_core *muxc;
	struct gpiomux *mux;
	struct i2c_adapter *parent;
	int (*deselect) (struct i2c_adapter *, void *, u32);
	unsigned initial_state, gpio_base;
	int i, ret;

	mux = devm_kzalloc(&pdev->dev, sizeof(*mux), GFP_KERNEL);
	if (!mux) {
		dev_err(&pdev->dev, "Cannot allocate gpiomux structure");
	if (!mux)
		return -ENOMEM;
	}

	platform_set_drvdata(pdev, mux);

	if (!dev_get_platdata(&pdev->dev)) {
		ret = i2c_mux_gpio_probe_dt(mux, pdev);
@@ -180,24 +174,23 @@ static int i2c_mux_gpio_probe(struct platform_device *pdev)
	if (!parent)
		return -EPROBE_DEFER;

	mux->parent = parent;
	mux->gpio_base = gpio_base;

	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_gpio_select, NULL);
	if (!muxc) {
		ret = -ENOMEM;
		goto alloc_failed;
	}
	muxc->priv = mux;

	platform_set_drvdata(pdev, muxc);

	mux->gpio_base = gpio_base;

	if (mux->data.idle != I2C_MUX_GPIO_NO_IDLE) {
		initial_state = mux->data.idle;
		deselect = i2c_mux_gpio_deselect;
		muxc->deselect = i2c_mux_gpio_deselect;
	} else {
		initial_state = mux->data.values[0];
		deselect = NULL;
	}

	for (i = 0; i < mux->data.n_gpios; i++) {
@@ -223,11 +216,8 @@ static int i2c_mux_gpio_probe(struct platform_device *pdev)
		u32 nr = mux->data.base_nr ? (mux->data.base_nr + i) : 0;
		unsigned int class = mux->data.classes ? mux->data.classes[i] : 0;

		mux->adap[i] = i2c_add_mux_adapter(parent, &pdev->dev, mux, nr,
						   mux->data.values[i], class,
						   i2c_mux_gpio_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;
		}
@@ -239,8 +229,7 @@ static int i2c_mux_gpio_probe(struct platform_device *pdev)
	return 0;

add_adapter_failed:
	for (; i > 0; i--)
		i2c_del_mux_adapter(mux->adap[i - 1]);
	i2c_mux_del_adapters(muxc);
	i = mux->data.n_gpios;
err_request_gpio:
	for (; i > 0; i--)
@@ -253,16 +242,16 @@ static int i2c_mux_gpio_probe(struct platform_device *pdev)

static int i2c_mux_gpio_remove(struct platform_device *pdev)
{
	struct gpiomux *mux = platform_get_drvdata(pdev);
	struct i2c_mux_core *muxc = platform_get_drvdata(pdev);
	struct gpiomux *mux = i2c_mux_priv(muxc);
	int i;

	for (i = 0; i < mux->data.n_values; i++)
		i2c_del_mux_adapter(mux->adap[i]);
	i2c_mux_del_adapters(muxc);

	for (i = 0; i < mux->data.n_gpios; i++)
		gpio_free(mux->gpio_base + mux->data.gpios[i]);

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

	return 0;
}