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: Peter Rosin <peda@xxxxxxxxxx> --- drivers/i2c/muxes/i2c-mux-reg.c | 69 +++++++++++++++-------------------------- 1 file changed, 25 insertions(+), 44 deletions(-) diff --git a/drivers/i2c/muxes/i2c-mux-reg.c b/drivers/i2c/muxes/i2c-mux-reg.c index 5fbd5bd0878f..6773cadf7c9f 100644 --- a/drivers/i2c/muxes/i2c-mux-reg.c +++ b/drivers/i2c/muxes/i2c-mux-reg.c @@ -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); @@ -85,7 +81,7 @@ static int i2c_mux_reg_deselect(struct i2c_adapter *adap, void *data, #ifdef CONFIG_OF static int i2c_mux_reg_probe_dt(struct regmux *mux, - struct platform_device *pdev) + struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; struct device_node *adapter_np, *child; @@ -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); @@ -161,7 +156,7 @@ static int i2c_mux_reg_probe_dt(struct regmux *mux, } #else static int i2c_mux_reg_probe_dt(struct regmux *mux, - struct platform_device *pdev) + struct platform_device *pdev) { return 0; } @@ -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; } -- 2.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-i2c" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html