Commit 4bbe7fb0 authored by Peter Rosin's avatar Peter Rosin Committed by Wolfram Sang

i2c: i2c-mux-pinctrl: 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 bb448147
...@@ -26,27 +26,22 @@ ...@@ -26,27 +26,22 @@
#include <linux/of.h> #include <linux/of.h>
struct i2c_mux_pinctrl { struct i2c_mux_pinctrl {
struct device *dev;
struct i2c_mux_pinctrl_platform_data *pdata; struct i2c_mux_pinctrl_platform_data *pdata;
struct pinctrl *pinctrl; struct pinctrl *pinctrl;
struct pinctrl_state **states; struct pinctrl_state **states;
struct pinctrl_state *state_idle; struct pinctrl_state *state_idle;
struct i2c_adapter *parent;
struct i2c_adapter **busses;
}; };
static int i2c_mux_pinctrl_select(struct i2c_adapter *adap, void *data, static int i2c_mux_pinctrl_select(struct i2c_mux_core *muxc, u32 chan)
u32 chan)
{ {
struct i2c_mux_pinctrl *mux = data; struct i2c_mux_pinctrl *mux = i2c_mux_priv(muxc);
return pinctrl_select_state(mux->pinctrl, mux->states[chan]); return pinctrl_select_state(mux->pinctrl, mux->states[chan]);
} }
static int i2c_mux_pinctrl_deselect(struct i2c_adapter *adap, void *data, static int i2c_mux_pinctrl_deselect(struct i2c_mux_core *muxc, u32 chan)
u32 chan)
{ {
struct i2c_mux_pinctrl *mux = data; struct i2c_mux_pinctrl *mux = i2c_mux_priv(muxc);
return pinctrl_select_state(mux->pinctrl, mux->state_idle); return pinctrl_select_state(mux->pinctrl, mux->state_idle);
} }
...@@ -64,15 +59,12 @@ static int i2c_mux_pinctrl_parse_dt(struct i2c_mux_pinctrl *mux, ...@@ -64,15 +59,12 @@ static int i2c_mux_pinctrl_parse_dt(struct i2c_mux_pinctrl *mux,
return 0; return 0;
mux->pdata = devm_kzalloc(&pdev->dev, sizeof(*mux->pdata), GFP_KERNEL); mux->pdata = devm_kzalloc(&pdev->dev, sizeof(*mux->pdata), GFP_KERNEL);
if (!mux->pdata) { if (!mux->pdata)
dev_err(mux->dev,
"Cannot allocate i2c_mux_pinctrl_platform_data\n");
return -ENOMEM; return -ENOMEM;
}
num_names = of_property_count_strings(np, "pinctrl-names"); num_names = of_property_count_strings(np, "pinctrl-names");
if (num_names < 0) { if (num_names < 0) {
dev_err(mux->dev, "Cannot parse pinctrl-names: %d\n", dev_err(&pdev->dev, "Cannot parse pinctrl-names: %d\n",
num_names); num_names);
return num_names; return num_names;
} }
...@@ -80,23 +72,22 @@ static int i2c_mux_pinctrl_parse_dt(struct i2c_mux_pinctrl *mux, ...@@ -80,23 +72,22 @@ static int i2c_mux_pinctrl_parse_dt(struct i2c_mux_pinctrl *mux,
mux->pdata->pinctrl_states = devm_kzalloc(&pdev->dev, mux->pdata->pinctrl_states = devm_kzalloc(&pdev->dev,
sizeof(*mux->pdata->pinctrl_states) * num_names, sizeof(*mux->pdata->pinctrl_states) * num_names,
GFP_KERNEL); GFP_KERNEL);
if (!mux->pdata->pinctrl_states) { if (!mux->pdata->pinctrl_states)
dev_err(mux->dev, "Cannot allocate pinctrl_states\n");
return -ENOMEM; return -ENOMEM;
}
for (i = 0; i < num_names; i++) { for (i = 0; i < num_names; i++) {
ret = of_property_read_string_index(np, "pinctrl-names", i, ret = of_property_read_string_index(np, "pinctrl-names", i,
&mux->pdata->pinctrl_states[mux->pdata->bus_count]); &mux->pdata->pinctrl_states[mux->pdata->bus_count]);
if (ret < 0) { if (ret < 0) {
dev_err(mux->dev, "Cannot parse pinctrl-names: %d\n", dev_err(&pdev->dev, "Cannot parse pinctrl-names: %d\n",
ret); ret);
return ret; return ret;
} }
if (!strcmp(mux->pdata->pinctrl_states[mux->pdata->bus_count], if (!strcmp(mux->pdata->pinctrl_states[mux->pdata->bus_count],
"idle")) { "idle")) {
if (i != num_names - 1) { if (i != num_names - 1) {
dev_err(mux->dev, "idle state must be last\n"); dev_err(&pdev->dev,
"idle state must be last\n");
return -EINVAL; return -EINVAL;
} }
mux->pdata->pinctrl_state_idle = "idle"; mux->pdata->pinctrl_state_idle = "idle";
...@@ -107,13 +98,13 @@ static int i2c_mux_pinctrl_parse_dt(struct i2c_mux_pinctrl *mux, ...@@ -107,13 +98,13 @@ static int i2c_mux_pinctrl_parse_dt(struct i2c_mux_pinctrl *mux,
adapter_np = of_parse_phandle(np, "i2c-parent", 0); adapter_np = of_parse_phandle(np, "i2c-parent", 0);
if (!adapter_np) { if (!adapter_np) {
dev_err(mux->dev, "Cannot parse i2c-parent\n"); dev_err(&pdev->dev, "Cannot parse i2c-parent\n");
return -ENODEV; return -ENODEV;
} }
adapter = of_find_i2c_adapter_by_node(adapter_np); adapter = of_find_i2c_adapter_by_node(adapter_np);
of_node_put(adapter_np); of_node_put(adapter_np);
if (!adapter) { if (!adapter) {
dev_err(mux->dev, "Cannot find parent bus\n"); dev_err(&pdev->dev, "Cannot find parent bus\n");
return -EPROBE_DEFER; return -EPROBE_DEFER;
} }
mux->pdata->parent_bus_num = i2c_adapter_id(adapter); mux->pdata->parent_bus_num = i2c_adapter_id(adapter);
...@@ -131,19 +122,15 @@ static inline int i2c_mux_pinctrl_parse_dt(struct i2c_mux_pinctrl *mux, ...@@ -131,19 +122,15 @@ static inline int i2c_mux_pinctrl_parse_dt(struct i2c_mux_pinctrl *mux,
static int i2c_mux_pinctrl_probe(struct platform_device *pdev) static int i2c_mux_pinctrl_probe(struct platform_device *pdev)
{ {
struct i2c_mux_core *muxc;
struct i2c_mux_pinctrl *mux; struct i2c_mux_pinctrl *mux;
int (*deselect)(struct i2c_adapter *, void *, u32);
int i, ret; int i, ret;
mux = devm_kzalloc(&pdev->dev, sizeof(*mux), GFP_KERNEL); mux = devm_kzalloc(&pdev->dev, sizeof(*mux), GFP_KERNEL);
if (!mux) { if (!mux) {
dev_err(&pdev->dev, "Cannot allocate i2c_mux_pinctrl\n");
ret = -ENOMEM; ret = -ENOMEM;
goto err; goto err;
} }
platform_set_drvdata(pdev, mux);
mux->dev = &pdev->dev;
mux->pdata = dev_get_platdata(&pdev->dev); mux->pdata = dev_get_platdata(&pdev->dev);
if (!mux->pdata) { if (!mux->pdata) {
...@@ -166,14 +153,15 @@ static int i2c_mux_pinctrl_probe(struct platform_device *pdev) ...@@ -166,14 +153,15 @@ static int i2c_mux_pinctrl_probe(struct platform_device *pdev)
goto err; goto err;
} }
mux->busses = devm_kzalloc(&pdev->dev, muxc = i2c_mux_alloc(NULL, &pdev->dev, mux->pdata->bus_count, 0, 0,
sizeof(*mux->busses) * mux->pdata->bus_count, i2c_mux_pinctrl_select, NULL);
GFP_KERNEL); if (!muxc) {
if (!mux->busses) {
dev_err(&pdev->dev, "Cannot allocate busses\n");
ret = -ENOMEM; ret = -ENOMEM;
goto err; goto err;
} }
muxc->priv = mux;
platform_set_drvdata(pdev, muxc);
mux->pinctrl = devm_pinctrl_get(&pdev->dev); mux->pinctrl = devm_pinctrl_get(&pdev->dev);
if (IS_ERR(mux->pinctrl)) { if (IS_ERR(mux->pinctrl)) {
...@@ -203,13 +191,11 @@ static int i2c_mux_pinctrl_probe(struct platform_device *pdev) ...@@ -203,13 +191,11 @@ static int i2c_mux_pinctrl_probe(struct platform_device *pdev)
goto err; goto err;
} }
deselect = i2c_mux_pinctrl_deselect; muxc->deselect = i2c_mux_pinctrl_deselect;
} else {
deselect = NULL;
} }
mux->parent = i2c_get_adapter(mux->pdata->parent_bus_num); muxc->parent = i2c_get_adapter(mux->pdata->parent_bus_num);
if (!mux->parent) { if (!muxc->parent) {
dev_err(&pdev->dev, "Parent adapter (%d) not found\n", dev_err(&pdev->dev, "Parent adapter (%d) not found\n",
mux->pdata->parent_bus_num); mux->pdata->parent_bus_num);
ret = -EPROBE_DEFER; ret = -EPROBE_DEFER;
...@@ -220,12 +206,8 @@ static int i2c_mux_pinctrl_probe(struct platform_device *pdev) ...@@ -220,12 +206,8 @@ static int i2c_mux_pinctrl_probe(struct platform_device *pdev)
u32 bus = mux->pdata->base_bus_num ? u32 bus = mux->pdata->base_bus_num ?
(mux->pdata->base_bus_num + i) : 0; (mux->pdata->base_bus_num + i) : 0;
mux->busses[i] = i2c_add_mux_adapter(mux->parent, &pdev->dev, ret = i2c_mux_add_adapter(muxc, bus, i, 0);
mux, bus, i, 0, if (ret) {
i2c_mux_pinctrl_select,
deselect);
if (!mux->busses[i]) {
ret = -ENODEV;
dev_err(&pdev->dev, "Failed to add adapter %d\n", i); dev_err(&pdev->dev, "Failed to add adapter %d\n", i);
goto err_del_adapter; goto err_del_adapter;
} }
...@@ -234,23 +216,18 @@ static int i2c_mux_pinctrl_probe(struct platform_device *pdev) ...@@ -234,23 +216,18 @@ static int i2c_mux_pinctrl_probe(struct platform_device *pdev)
return 0; return 0;
err_del_adapter: err_del_adapter:
for (; i > 0; i--) i2c_mux_del_adapters(muxc);
i2c_del_mux_adapter(mux->busses[i - 1]); i2c_put_adapter(muxc->parent);
i2c_put_adapter(mux->parent);
err: err:
return ret; return ret;
} }
static int i2c_mux_pinctrl_remove(struct platform_device *pdev) static int i2c_mux_pinctrl_remove(struct platform_device *pdev)
{ {
struct i2c_mux_pinctrl *mux = platform_get_drvdata(pdev); struct i2c_mux_core *muxc = platform_get_drvdata(pdev);
int i;
for (i = 0; i < mux->pdata->bus_count; i++)
i2c_del_mux_adapter(mux->busses[i]);
i2c_put_adapter(mux->parent);
i2c_mux_del_adapters(muxc);
i2c_put_adapter(muxc->parent);
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment